diff --git a/Bender.lock b/Bender.lock index 5c6de69..eb0f76a 100644 --- a/Bender.lock +++ b/Bender.lock @@ -7,8 +7,8 @@ packages: dependencies: - common_cells axi: - revision: 2f395b176bee1c769c80f060a4345fda965bb04b - version: 0.38.0 + revision: f07498d53ecd5518b277c7d213ec3b71ca4df93c + version: 0.39.7 source: Git: https://github.com/pulp-platform/axi.git dependencies: @@ -16,32 +16,22 @@ packages: - common_verification - tech_cells_generic common_cells: - revision: aed978efcef722859025085ae72e52c41ea45b32 - version: 1.31.0 + revision: 9afda9abb565971649c2aa0985639c096f351171 + version: 1.38.0 source: Git: https://github.com/pulp-platform/common_cells.git dependencies: - common_verification - tech_cells_generic common_verification: - revision: 9c07fa860593b2caabd9b5681740c25fac04b878 - version: 0.2.3 + revision: fb1885f48ea46164a10568aeff51884389f67ae3 + version: 0.2.5 source: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] - register_interface: - revision: 3b2bf592100b769977c76e51812c55cd742882f6 - version: 0.4.1 - source: - Git: https://github.com/pulp-platform/register_interface.git - dependencies: - - apb - - axi - - common_cells - - common_verification tech_cells_generic: - revision: a9cae21902e75b1434328ecf36f85327ba5717de - version: 0.2.11 + revision: 7968dd6e6180df2c644636bc6d2908a49f2190cf + version: 0.2.13 source: Git: https://github.com/pulp-platform/tech_cells_generic.git dependencies: diff --git a/Bender.yml b/Bender.yml index 4a7bf5d..1025f1e 100644 --- a/Bender.yml +++ b/Bender.yml @@ -9,8 +9,8 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.29.0 } - register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.1 } axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.39.1 } + apb: { git: "https://github.com/pulp-platform/apb.git", version: 0.2.4 } sources: # Level 1 diff --git a/Makefile b/Makefile index 529cec6..fa5715b 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,32 @@ BENDER ?= bender -REG_PATH = $(shell $(BENDER) path register_interface) -REG_TOOL = $(REG_PATH)/vendor/lowrisc_opentitan/util/regtool.py +PEAKRDL ?= peakrdl -REGS_HJSON = src/err_unit_regs.hjson +.PHONY: gen_regs +gen_regs: src/bus_err_unit_reg_pkg.sv src/bus_err_unit_reg_top.sv +gen_regs: doc/bus_err_unit_reg.md +gen_regs: driver/bus_err_unit_reg.h driver/bus_err_unit_reg_addrmap.h +gen_regs: doc/axi_bus_err_unit_reg.md +gen_regs: driver/axi_bus_err_unit_reg.h driver/axi_bus_err_unit_reg_addrmap.h -gen_regs: - python $(REG_TOOL) $(REGS_HJSON) -t src -r - python $(REG_TOOL) $(REGS_HJSON) -D > driver/bus_err_unit.h +src/bus_err_unit_reg_pkg.sv src/bus_err_unit_reg_top.sv: rdl/bus_err_unit.rdl + $(PEAKRDL) regblock $< -o src --cpuif apb4-flat --default-reset arst_n --module-name bus_err_unit_reg_top --package-name bus_err_unit_reg_pkg + +doc/bus_err_unit_reg.md: rdl/bus_err_unit.rdl + $(PEAKRDL) markdown $< -o $@ + +driver/bus_err_unit_reg.h: rdl/bus_err_unit.rdl + $(PEAKRDL) c-header $< -o $@ + +driver/bus_err_unit_reg_addrmap.h: rdl/bus_err_unit.rdl + $(PEAKRDL) raw-header $< -o $@ --format c + +doc/axi_bus_err_unit_reg.md: rdl/axi_bus_err_unit.rdl rdl/bus_err_unit.rdl + $(PEAKRDL) markdown $< -o $@ -I rdl + +driver/axi_bus_err_unit_reg.h: rdl/axi_bus_err_unit.rdl rdl/bus_err_unit.rdl + $(PEAKRDL) c-header $< -o $@ -I rdl + +driver/axi_bus_err_unit_reg_addrmap.h: rdl/axi_bus_err_unit.rdl rdl/bus_err_unit.rdl + $(PEAKRDL) raw-header $< -o $@ --format c -I rdl diff --git a/doc/axi_bus_err_unit_reg.md b/doc/axi_bus_err_unit_reg.md new file mode 100644 index 0000000..5432a52 --- /dev/null +++ b/doc/axi_bus_err_unit_reg.md @@ -0,0 +1,155 @@ + + +## axi_bus_err_unit address map + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x30 + +|Offset| Identifier |Name| +|------|--------------|----| +| 0x00 |write_err_unit| — | +| 0x20 | read_err_unit| — | + +## write_err_unit address map + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x10 + +|Offset| Identifier |Name| +|------|------------|----| +| 0x0 | err_addr | — | +| 0x4 |err_addr_top| — | +| 0x8 | err_code | — | +| 0xC | meta | — | + +### err_addr register + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x4 + +|Bits|Identifier|Access|Reset| Name | +|----|----------|------|-----|--------| +|31:0| err_addr | r | 0x0 |err_addr| + +#### err_addr field + +

Address of the bus error

+ +### err_addr_top register + +- Absolute Address: 0x4 +- Base Offset: 0x4 +- Size: 0x4 + +|Bits| Identifier |Access|Reset| Name | +|----|------------|------|-----|------------| +|31:0|err_addr_top| r | 0x0 |err_addr_top| + +#### err_addr_top field + +

Top of the address of the bus error

+ +### err_code register + +- Absolute Address: 0x8 +- Base Offset: 0x8 +- Size: 0x4 + +|Bits|Identifier|Access|Reset| Name | +|----|----------|------|-----|--------| +|31:0| err_code | r | 0x0 |err_code| + +#### err_code field + +

Type of the bus error

+ +### meta register + +- Absolute Address: 0xC +- Base Offset: 0xC +- Size: 0x4 + +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +|31:0| meta | r | 0x0 |meta| + +#### meta field + +

Meta information of the bus error

+ +## read_err_unit address map + +- Absolute Address: 0x20 +- Base Offset: 0x20 +- Size: 0x10 + +|Offset| Identifier |Name| +|------|------------|----| +| 0x0 | err_addr | — | +| 0x4 |err_addr_top| — | +| 0x8 | err_code | — | +| 0xC | meta | — | + +### err_addr register + +- Absolute Address: 0x20 +- Base Offset: 0x0 +- Size: 0x4 + +|Bits|Identifier|Access|Reset| Name | +|----|----------|------|-----|--------| +|31:0| err_addr | r | 0x0 |err_addr| + +#### err_addr field + +

Address of the bus error

+ +### err_addr_top register + +- Absolute Address: 0x24 +- Base Offset: 0x4 +- Size: 0x4 + +|Bits| Identifier |Access|Reset| Name | +|----|------------|------|-----|------------| +|31:0|err_addr_top| r | 0x0 |err_addr_top| + +#### err_addr_top field + +

Top of the address of the bus error

+ +### err_code register + +- Absolute Address: 0x28 +- Base Offset: 0x8 +- Size: 0x4 + +|Bits|Identifier|Access|Reset| Name | +|----|----------|------|-----|--------| +|31:0| err_code | r | 0x0 |err_code| + +#### err_code field + +

Type of the bus error

+ +### meta register + +- Absolute Address: 0x2C +- Base Offset: 0xC +- Size: 0x4 + +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +|31:0| meta | r | 0x0 |meta| + +#### meta field + +

Meta information of the bus error

diff --git a/doc/bus_err_unit_reg.md b/doc/bus_err_unit_reg.md new file mode 100644 index 0000000..d10cf18 --- /dev/null +++ b/doc/bus_err_unit_reg.md @@ -0,0 +1,75 @@ + + +## bus_err_unit address map + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x10 + +|Offset| Identifier |Name| +|------|------------|----| +| 0x0 | err_addr | — | +| 0x4 |err_addr_top| — | +| 0x8 | err_code | — | +| 0xC | meta | — | + +### err_addr register + +- Absolute Address: 0x0 +- Base Offset: 0x0 +- Size: 0x4 + +|Bits|Identifier|Access|Reset| Name | +|----|----------|------|-----|--------| +|31:0| err_addr | r | 0x0 |err_addr| + +#### err_addr field + +

Address of the bus error

+ +### err_addr_top register + +- Absolute Address: 0x4 +- Base Offset: 0x4 +- Size: 0x4 + +|Bits| Identifier |Access|Reset| Name | +|----|------------|------|-----|------------| +|31:0|err_addr_top| r | 0x0 |err_addr_top| + +#### err_addr_top field + +

Top of the address of the bus error

+ +### err_code register + +- Absolute Address: 0x8 +- Base Offset: 0x8 +- Size: 0x4 + +|Bits|Identifier|Access|Reset| Name | +|----|----------|------|-----|--------| +|31:0| err_code | r | 0x0 |err_code| + +#### err_code field + +

Type of the bus error

+ +### meta register + +- Absolute Address: 0xC +- Base Offset: 0xC +- Size: 0x4 + +|Bits|Identifier|Access|Reset|Name| +|----|----------|------|-----|----| +|31:0| meta | r | 0x0 |meta| + +#### meta field + +

Meta information of the bus error

diff --git a/driver/axi_bus_err_unit_reg.h b/driver/axi_bus_err_unit_reg.h new file mode 100644 index 0000000..49e60b9 --- /dev/null +++ b/driver/axi_bus_err_unit_reg.h @@ -0,0 +1,60 @@ +// Generated by PeakRDL-cheader - A free and open-source header generator +// https://github.com/SystemRDL/PeakRDL-cheader + +#ifndef AXI_BUS_ERR_UNIT_REG_H +#define AXI_BUS_ERR_UNIT_REG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Reg - bus_err_unit::err_addr +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_bm 0xffffffff +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_bp 0 +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_bw 32 +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_reset 0x0 + +// Reg - bus_err_unit::err_addr_top +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_bm 0xffffffff +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_bp 0 +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_bw 32 +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_reset 0x0 + +// Reg - bus_err_unit::err_code +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_bm 0xffffffff +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_bp 0 +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_bw 32 +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_reset 0x0 + +// Reg - bus_err_unit::meta +#define BUS_ERR_UNIT__META__META_bm 0xffffffff +#define BUS_ERR_UNIT__META__META_bp 0 +#define BUS_ERR_UNIT__META__META_bw 32 +#define BUS_ERR_UNIT__META__META_reset 0x0 + +// Addrmap - bus_err_unit +typedef struct __attribute__ ((__packed__)) { + uint32_t err_addr; + uint32_t err_addr_top; + uint32_t err_code; + uint32_t meta; +} bus_err_unit_t; + +// Addrmap - axi_bus_err_unit +typedef struct __attribute__ ((__packed__)) { + bus_err_unit_t write_err_unit; + uint8_t RESERVED_10_1f[0x10]; + bus_err_unit_t read_err_unit; +} axi_bus_err_unit_t; + + +static_assert(sizeof(axi_bus_err_unit_t) == 0x30, "Packing error"); + +#ifdef __cplusplus +} +#endif + +#endif /* AXI_BUS_ERR_UNIT_REG_H */ diff --git a/driver/axi_bus_err_unit_reg_addrmap.h b/driver/axi_bus_err_unit_reg_addrmap.h new file mode 100644 index 0000000..a08a4bc --- /dev/null +++ b/driver/axi_bus_err_unit_reg_addrmap.h @@ -0,0 +1,42 @@ +#ifndef AXI_BUS_ERR_UNIT_H +#define AXI_BUS_ERR_UNIT_H + + +#define AXI_BUS_ERR_UNIT_BASE_ADDR 0x00000000 +#define AXI_BUS_ERR_UNIT_SIZE 0x00000030 + + +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_BASE_ADDR 0x00000000 +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_SIZE 0x00000010 + +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_ERR_ADDR_REG_ADDR 0x00000000 +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_ERR_ADDR_REG_OFFSET 0x00000000 + +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_ERR_ADDR_TOP_REG_ADDR 0x00000004 +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_ERR_ADDR_TOP_REG_OFFSET 0x00000004 + +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_ERR_CODE_REG_ADDR 0x00000008 +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_ERR_CODE_REG_OFFSET 0x00000008 + +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_META_REG_ADDR 0x0000000C +#define AXI_BUS_ERR_UNIT_WRITE_ERR_UNIT_META_REG_OFFSET 0x0000000C + + +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_BASE_ADDR 0x00000020 +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_SIZE 0x00000010 + +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_ERR_ADDR_REG_ADDR 0x00000020 +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_ERR_ADDR_REG_OFFSET 0x00000000 + +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_ERR_ADDR_TOP_REG_ADDR 0x00000024 +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_ERR_ADDR_TOP_REG_OFFSET 0x00000004 + +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_ERR_CODE_REG_ADDR 0x00000028 +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_ERR_CODE_REG_OFFSET 0x00000008 + +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_META_REG_ADDR 0x0000002C +#define AXI_BUS_ERR_UNIT_READ_ERR_UNIT_META_REG_OFFSET 0x0000000C + + + +#endif /* AXI_BUS_ERR_UNIT_H */ diff --git a/driver/bus_err_unit.h b/driver/bus_err_unit.h deleted file mode 100644 index 2ed1a0a..0000000 --- a/driver/bus_err_unit.h +++ /dev/null @@ -1,35 +0,0 @@ -// Generated register defines for bus_err_unit - -// Copyright information found in source file: -// Copyright 2023 ETH Zurich and University of Bologna. - -// Licensing information found in source file: -// -// SPDX-License-Identifier: SHL-0.51 - -#ifndef _BUS_ERR_UNIT_REG_DEFS_ -#define _BUS_ERR_UNIT_REG_DEFS_ - -#ifdef __cplusplus -extern "C" { -#endif -// Register width -#define BUS_ERR_UNIT_PARAM_REG_WIDTH 32 - -// Address of the bus error -#define BUS_ERR_UNIT_ERR_ADDR_REG_OFFSET 0x0 - -// Top of the address of the bus error -#define BUS_ERR_UNIT_ERR_ADDR_TOP_REG_OFFSET 0x4 - -// Error code of the bus error -#define BUS_ERR_UNIT_ERR_CODE_REG_OFFSET 0x8 - -// Meta information of the bus error -#define BUS_ERR_UNIT_META_REG_OFFSET 0xc - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _BUS_ERR_UNIT_REG_DEFS_ -// End generated register defines for bus_err_unit \ No newline at end of file diff --git a/driver/bus_err_unit_reg.h b/driver/bus_err_unit_reg.h new file mode 100644 index 0000000..70463a6 --- /dev/null +++ b/driver/bus_err_unit_reg.h @@ -0,0 +1,53 @@ +// Generated by PeakRDL-cheader - A free and open-source header generator +// https://github.com/SystemRDL/PeakRDL-cheader + +#ifndef BUS_ERR_UNIT_REG_H +#define BUS_ERR_UNIT_REG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Reg - bus_err_unit::err_addr +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_bm 0xffffffff +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_bp 0 +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_bw 32 +#define BUS_ERR_UNIT__ERR_ADDR__ERR_ADDR_reset 0x0 + +// Reg - bus_err_unit::err_addr_top +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_bm 0xffffffff +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_bp 0 +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_bw 32 +#define BUS_ERR_UNIT__ERR_ADDR_TOP__ERR_ADDR_TOP_reset 0x0 + +// Reg - bus_err_unit::err_code +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_bm 0xffffffff +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_bp 0 +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_bw 32 +#define BUS_ERR_UNIT__ERR_CODE__ERR_CODE_reset 0x0 + +// Reg - bus_err_unit::meta +#define BUS_ERR_UNIT__META__META_bm 0xffffffff +#define BUS_ERR_UNIT__META__META_bp 0 +#define BUS_ERR_UNIT__META__META_bw 32 +#define BUS_ERR_UNIT__META__META_reset 0x0 + +// Addrmap - bus_err_unit +typedef struct __attribute__ ((__packed__)) { + uint32_t err_addr; + uint32_t err_addr_top; + uint32_t err_code; + uint32_t meta; +} bus_err_unit_t; + + +static_assert(sizeof(bus_err_unit_t) == 0x10, "Packing error"); + +#ifdef __cplusplus +} +#endif + +#endif /* BUS_ERR_UNIT_REG_H */ diff --git a/driver/bus_err_unit_reg_addrmap.h b/driver/bus_err_unit_reg_addrmap.h new file mode 100644 index 0000000..be8a216 --- /dev/null +++ b/driver/bus_err_unit_reg_addrmap.h @@ -0,0 +1,22 @@ +#ifndef BUS_ERR_UNIT_H +#define BUS_ERR_UNIT_H + + +#define BUS_ERR_UNIT_BASE_ADDR 0x00000000 +#define BUS_ERR_UNIT_SIZE 0x00000010 + +#define BUS_ERR_UNIT_ERR_ADDR_REG_ADDR 0x00000000 +#define BUS_ERR_UNIT_ERR_ADDR_REG_OFFSET 0x00000000 + +#define BUS_ERR_UNIT_ERR_ADDR_TOP_REG_ADDR 0x00000004 +#define BUS_ERR_UNIT_ERR_ADDR_TOP_REG_OFFSET 0x00000004 + +#define BUS_ERR_UNIT_ERR_CODE_REG_ADDR 0x00000008 +#define BUS_ERR_UNIT_ERR_CODE_REG_OFFSET 0x00000008 + +#define BUS_ERR_UNIT_META_REG_ADDR 0x0000000C +#define BUS_ERR_UNIT_META_REG_OFFSET 0x0000000C + + + +#endif /* BUS_ERR_UNIT_H */ diff --git a/rdl/axi_bus_err_unit.rdl b/rdl/axi_bus_err_unit.rdl new file mode 100644 index 0000000..101bd70 --- /dev/null +++ b/rdl/axi_bus_err_unit.rdl @@ -0,0 +1,17 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Author: Michael Rogenmoser + +`ifndef AXI_BUS_ERR_UNIT_RDL +`define AXI_BUS_ERR_UNIT_RDL + +`include "bus_err_unit.rdl" + +addrmap axi_bus_err_unit { + bus_err_unit write_err_unit @0x0; + bus_err_unit read_err_unit @0x20; +}; + +`endif // AXI_BUS_ERR_UNIT_RDL diff --git a/rdl/bus_err_unit.rdl b/rdl/bus_err_unit.rdl new file mode 100644 index 0000000..f723366 --- /dev/null +++ b/rdl/bus_err_unit.rdl @@ -0,0 +1,55 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Author: Michael Rogenmoser + +`ifndef BUS_ERR_UNIT_RDL +`define BUS_ERR_UNIT_RDL + +addrmap bus_err_unit { + + reg err_addr { + field { + name = "err_addr"; + desc = "Address of the bus error"; + sw = r; + hw = w; + } err_addr[31:0] = 0x0; + }; + + reg err_addr_top { + field { + name = "err_addr_top"; + desc = "Top of the address of the bus error"; + sw = r; + hw = w; + } err_addr_top[31:0] = 0x0; + }; + + reg err_code { + field { + name = "err_code"; + desc = "Type of the bus error"; + sw = r; + hw = rw; + // TODO: hwre + } err_code[31:0] = 0x0; + }; + + reg meta { + field { + name = "meta"; + desc = "Meta information of the bus error"; + sw = r; + hw = rw; + } meta[31:0] = 0x0; + }; + + external err_addr err_addr; + external err_addr_top err_addr_top; + external err_code err_code; + external meta meta; +}; + +`endif // BUS_ERR_UNIT_RDL diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7d0588d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 + +peakrdl +peakrdl-cheader +peakrdl-markdown +peakrdl-rawheader @ git+github.com/micprog/peakrdl-rawheader.git diff --git a/src/axi_err_unit_wrap.sv b/src/axi_err_unit_wrap.sv index e53b4a7..5b8c1a8 100644 --- a/src/axi_err_unit_wrap.sv +++ b/src/axi_err_unit_wrap.sv @@ -15,8 +15,8 @@ module axi_err_unit_wrap #( parameter bit DropOldest = 1'b0, parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic + parameter type apb_req_t = logic, + parameter type apb_rsp_t = logic ) ( input logic clk_i, input logic rst_ni, @@ -27,14 +27,14 @@ module axi_err_unit_wrap #( output logic [1:0] err_irq_o, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o + input apb_req_t apb_req_i, + output apb_rsp_t apb_rsp_o ); logic [2**IdWidth-1:0] write_req_hs_valid, write_rsp_hs_valid, read_req_hs_valid, read_rsp_hs_valid, amo_r_req_hs_valid; logic [UserErrBits+2-1:0] write_err, read_err; - reg_req_t [1:0] reg_req_internal; - reg_rsp_t [1:0] reg_rsp_internal; + apb_req_t [1:0] apb_req_internal; + apb_rsp_t [1:0] apb_rsp_internal; for (genvar i = 0; i < 2**IdWidth; i++) begin assign write_req_hs_valid[i] = axi_req_i.aw_valid & axi_rsp_i.aw_ready & (axi_req_i.aw.id == i); @@ -53,18 +53,16 @@ module axi_err_unit_wrap #( assign read_err[UserErrBits+2-1:2] = axi_rsp_i.r.user[UserErrBits+UserErrBitsOffset-1:UserErrBitsOffset]; end - reg_demux #( - .NoPorts ( 2 ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_t ) - ) i_reg_demux ( - .clk_i, - .rst_ni, - .in_select_i(reg_req_i.addr[5]), - .in_req_i (reg_req_i), - .in_rsp_o (reg_rsp_o), - .out_req_o (reg_req_internal), - .out_rsp_i (reg_rsp_internal) + apb_demux #( + .NoMstPorts ( 2 ), + .req_t ( apb_req_t ), + .resp_t ( apb_rsp_t ) + ) i_apb_demux ( + .select_i (apb_req_i.addr[5]), + .slv_req_i (apb_req_i), + .slv_resp_o (apb_rsp_o), + .mst_req_o (apb_req_internal), + .mst_resp_i (apb_rsp_internal) ); bus_err_unit #( @@ -76,8 +74,8 @@ module axi_err_unit_wrap #( .NumReqPorts (1), .NumChannels (2**IdWidth), .DropOldest (DropOldest), - .reg_req_t (reg_req_t), - .reg_rsp_t (reg_rsp_t) + .apb_req_t (apb_req_t), + .apb_rsp_t (apb_rsp_t) ) i_write_err_unit ( .clk_i, .rst_ni, @@ -92,8 +90,8 @@ module axi_err_unit_wrap #( .err_irq_o ( err_irq_o[0] ), - .reg_req_i (reg_req_internal[0]), - .reg_rsp_o (reg_rsp_internal[0]) + .apb_req_i (apb_req_internal[0]), + .apb_rsp_o (apb_rsp_internal[0]) ); bus_err_unit #( @@ -105,8 +103,8 @@ module axi_err_unit_wrap #( .NumReqPorts (2), .NumChannels (2**IdWidth), .DropOldest (DropOldest), - .reg_req_t (reg_req_t), - .reg_rsp_t (reg_rsp_t) + .apb_req_t (apb_req_t), + .apb_rsp_t (apb_rsp_t) ) i_read_err_unit ( .clk_i, @@ -122,8 +120,8 @@ module axi_err_unit_wrap #( .err_irq_o ( err_irq_o[1] ), - .reg_req_i (reg_req_internal[1]), - .reg_rsp_o (reg_rsp_internal[1]) + .apb_req_i (apb_req_internal[1]), + .apb_rsp_o (apb_rsp_internal[1]) ); diff --git a/src/bus_err_unit.sv b/src/bus_err_unit.sv index 26d15fd..8a1967f 100644 --- a/src/bus_err_unit.sv +++ b/src/bus_err_unit.sv @@ -14,8 +14,8 @@ module bus_err_unit #( parameter int unsigned NumReqPorts = 1, parameter int unsigned NumChannels = 1, // Channels are one-hot! parameter bit DropOldest = 1'b0, - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic + parameter type apb_req_t = logic, + parameter type apb_rsp_t = logic ) ( input logic clk_i, input logic rst_ni, @@ -30,8 +30,8 @@ module bus_err_unit #( output logic err_irq_o, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o + input apb_req_t apb_req_i, + output apb_rsp_t apb_rsp_o ); @@ -40,39 +40,48 @@ module bus_err_unit #( logic [ ErrBits-1:0] read_err_err; logic read_err_overflow; - bus_err_unit_reg_pkg::bus_err_unit_reg2hw_t reg2hw; - bus_err_unit_reg_pkg::bus_err_unit_hw2reg_t hw2reg; + bus_err_unit_reg_pkg::bus_err_unit__out_t reg2hw; + bus_err_unit_reg_pkg::bus_err_unit__in_t hw2reg; - assign hw2reg.err_addr.d = read_err_addr[31:0]; + assign hw2reg.err_addr.rd_data.err_addr = read_err_addr[31:0]; if (AddrWidth > 32) begin always_comb begin - hw2reg.err_addr_top.d = '0; - hw2reg.err_addr_top.d[AddrWidth-32-1:0] = read_err_addr[AddrWidth-1:32]; + hw2reg.err_addr_top.rd_data.err_addr_top = '0; + hw2reg.err_addr_top.rd_data.err_addr_top[AddrWidth-32-1:0] = read_err_addr[AddrWidth-1:32]; end end else begin - assign hw2reg.err_addr_top.d = '0; + assign hw2reg.err_addr_top.rd_data.err_addr_top = '0; end always_comb begin : proc_err_code - hw2reg.err_code.d = '0; - hw2reg.err_code.d[ErrBits-1:0] = read_err_err; - hw2reg.err_code.d[31] = read_err_overflow; + hw2reg.err_code.rd_data.err_code = '0; + hw2reg.err_code.rd_data.err_code[ErrBits-1:0] = read_err_err; + hw2reg.err_code.rd_data.err_code[31] = read_err_overflow; end always_comb begin - hw2reg.meta.d = '0; - hw2reg.meta.d[MetaDataWidth-1:0] = read_err_meta; + hw2reg.meta.rd_data.meta = '0; + hw2reg.meta.rd_data.meta[MetaDataWidth-1:0] = read_err_meta; end - bus_err_unit_reg_top #( - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ) - ) i_regs ( - .clk_i, - .rst_ni, - .reg_req_i, - .reg_rsp_o, - .reg2hw (reg2hw), - .hw2reg (hw2reg), - .devmode_i ('0) + assign hw2reg.err_addr.rd_ack = reg2hw.err_addr.req & ~reg2hw.err_addr.req_is_wr; + assign hw2reg.err_addr_top.rd_ack = reg2hw.err_addr_top.req & ~reg2hw.err_addr_top.req_is_wr; + assign hw2reg.err_code.rd_ack = reg2hw.err_code.req & ~reg2hw.err_code.req_is_wr; + assign hw2reg.meta.rd_ack = reg2hw.meta.req & ~reg2hw.meta.req_is_wr; + + bus_err_unit_reg_top i_regs ( + .clk (clk_i), + .arst_n (rst_ni), + .s_apb_psel (apb_req_i.psel), + .s_apb_penable (apb_req_i.penable), + .s_apb_pwrite (apb_req_i.pwrite), + .s_apb_pprot (apb_req_i.pprot), + .s_apb_paddr (apb_req_i.paddr[bus_err_unit_reg_pkg::BUS_ERR_UNIT_REG_TOP_MIN_ADDR_WIDTH-1:0]), + .s_apb_pwdata (apb_req_i.pwdata), + .s_apb_pstrb (apb_req_i.pstrb), + .s_apb_pready (apb_rsp_o.pready), + .s_apb_prdata (apb_rsp_o.prdata), + .s_apb_pslverr (apb_rsp_o.pslverr), + .hwif_out (reg2hw), + .hwif_in (hw2reg) ); bus_err_unit_bare #( @@ -98,7 +107,7 @@ module bus_err_unit #( .err_irq_o, - .err_fifo_pop_i ( reg2hw.err_code.re ), + .err_fifo_pop_i ( reg2hw.err_code.req & ~reg2hw.err_code.req_is_wr ), .err_code_o ( read_err_err ), .err_addr_o ( read_err_addr ), .err_meta_o ( read_err_meta ), diff --git a/src/bus_err_unit_reg_pkg.sv b/src/bus_err_unit_reg_pkg.sv index c05d536..fee9e90 100644 --- a/src/bus_err_unit_reg_pkg.sv +++ b/src/bus_err_unit_reg_pkg.sv @@ -1,79 +1,81 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock package bus_err_unit_reg_pkg; - // Address widths within the block - parameter int BlockAw = 4; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic [31:0] q; - logic re; - } bus_err_unit_reg2hw_err_code_reg_t; - - typedef struct packed { - logic [31:0] d; - } bus_err_unit_hw2reg_err_addr_reg_t; - - typedef struct packed { - logic [31:0] d; - } bus_err_unit_hw2reg_err_addr_top_reg_t; - - typedef struct packed { - logic [31:0] d; - } bus_err_unit_hw2reg_err_code_reg_t; - - typedef struct packed { - logic [31:0] d; - } bus_err_unit_hw2reg_meta_reg_t; - - // Register -> HW type - typedef struct packed { - bus_err_unit_reg2hw_err_code_reg_t err_code; // [32:0] - } bus_err_unit_reg2hw_t; - - // HW -> register type - typedef struct packed { - bus_err_unit_hw2reg_err_addr_reg_t err_addr; // [127:96] - bus_err_unit_hw2reg_err_addr_top_reg_t err_addr_top; // [95:64] - bus_err_unit_hw2reg_err_code_reg_t err_code; // [63:32] - bus_err_unit_hw2reg_meta_reg_t meta; // [31:0] - } bus_err_unit_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] BUS_ERR_UNIT_ERR_ADDR_OFFSET = 4'h 0; - parameter logic [BlockAw-1:0] BUS_ERR_UNIT_ERR_ADDR_TOP_OFFSET = 4'h 4; - parameter logic [BlockAw-1:0] BUS_ERR_UNIT_ERR_CODE_OFFSET = 4'h 8; - parameter logic [BlockAw-1:0] BUS_ERR_UNIT_META_OFFSET = 4'h c; - - // Reset values for hwext registers and their fields - parameter logic [31:0] BUS_ERR_UNIT_ERR_ADDR_RESVAL = 32'h 0; - parameter logic [31:0] BUS_ERR_UNIT_ERR_ADDR_TOP_RESVAL = 32'h 0; - parameter logic [31:0] BUS_ERR_UNIT_ERR_CODE_RESVAL = 32'h 0; - parameter logic [31:0] BUS_ERR_UNIT_META_RESVAL = 32'h 0; - - // Register index - typedef enum int { - BUS_ERR_UNIT_ERR_ADDR, - BUS_ERR_UNIT_ERR_ADDR_TOP, - BUS_ERR_UNIT_ERR_CODE, - BUS_ERR_UNIT_META - } bus_err_unit_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] BUS_ERR_UNIT_PERMIT [4] = '{ - 4'b 1111, // index[0] BUS_ERR_UNIT_ERR_ADDR - 4'b 1111, // index[1] BUS_ERR_UNIT_ERR_ADDR_TOP - 4'b 1111, // index[2] BUS_ERR_UNIT_ERR_CODE - 4'b 1111 // index[3] BUS_ERR_UNIT_META - }; - + localparam BUS_ERR_UNIT_REG_TOP_DATA_WIDTH = 32; + localparam BUS_ERR_UNIT_REG_TOP_MIN_ADDR_WIDTH = 4; + localparam BUS_ERR_UNIT_REG_TOP_SIZE = 'h10; + + + + typedef struct packed { + logic [31:0] err_addr; + } bus_err_unit__err_addr__external__fields__in_t; + + typedef struct { + logic rd_ack; + bus_err_unit__err_addr__external__fields__in_t rd_data; + } bus_err_unit__err_addr__external__in_t; + + typedef struct packed { + logic [31:0] err_addr_top; + } bus_err_unit__err_addr_top__external__fields__in_t; + + typedef struct { + logic rd_ack; + bus_err_unit__err_addr_top__external__fields__in_t rd_data; + } bus_err_unit__err_addr_top__external__in_t; + + typedef struct packed { + logic [31:0] err_code; + } bus_err_unit__err_code__external__fields__in_t; + + typedef struct { + logic rd_ack; + bus_err_unit__err_code__external__fields__in_t rd_data; + } bus_err_unit__err_code__external__in_t; + + typedef struct packed { + logic [31:0] meta; + } bus_err_unit__meta__external__fields__in_t; + + typedef struct { + logic rd_ack; + bus_err_unit__meta__external__fields__in_t rd_data; + } bus_err_unit__meta__external__in_t; + + typedef struct { + bus_err_unit__err_addr__external__in_t err_addr; + bus_err_unit__err_addr_top__external__in_t err_addr_top; + bus_err_unit__err_code__external__in_t err_code; + bus_err_unit__meta__external__in_t meta; + } bus_err_unit__in_t; + + typedef struct { + logic req; + logic req_is_wr; + } bus_err_unit__err_addr__external__out_t; + + typedef struct { + logic req; + logic req_is_wr; + } bus_err_unit__err_addr_top__external__out_t; + + typedef struct { + logic req; + logic req_is_wr; + } bus_err_unit__err_code__external__out_t; + + typedef struct { + logic req; + logic req_is_wr; + } bus_err_unit__meta__external__out_t; + + typedef struct { + bus_err_unit__err_addr__external__out_t err_addr; + bus_err_unit__err_addr_top__external__out_t err_addr_top; + bus_err_unit__err_code__external__out_t err_code; + bus_err_unit__meta__external__out_t meta; + } bus_err_unit__out_t; endpackage - diff --git a/src/bus_err_unit_reg_top.sv b/src/bus_err_unit_reg_top.sv index c35d7ff..ed50fd9 100644 --- a/src/bus_err_unit_reg_top.sv +++ b/src/bus_err_unit_reg_top.sv @@ -1,265 +1,219 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module bus_err_unit_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 4 -) ( - input logic clk_i, - input logic rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output bus_err_unit_reg_pkg::bus_err_unit_reg2hw_t reg2hw, // Write - input bus_err_unit_reg_pkg::bus_err_unit_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import bus_err_unit_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [BlockAw-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic [31:0] err_addr_qs; - logic err_addr_re; - logic [31:0] err_addr_top_qs; - logic err_addr_top_re; - logic [31:0] err_code_qs; - logic err_code_re; - logic [31:0] meta_qs; - logic meta_re; - - // Register instances - // R[err_addr]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_err_addr ( - .re (err_addr_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.err_addr.d), - .qre (), - .qe (), - .q (), - .qs (err_addr_qs) - ); - - - // R[err_addr_top]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_err_addr_top ( - .re (err_addr_top_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.err_addr_top.d), - .qre (), - .qe (), - .q (), - .qs (err_addr_top_qs) - ); - - - // R[err_code]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_err_code ( - .re (err_code_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.err_code.d), - .qre (reg2hw.err_code.re), - .qe (), - .q (reg2hw.err_code.q ), - .qs (err_code_qs) - ); - - - // R[meta]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_meta ( - .re (meta_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.meta.d), - .qre (), - .qe (), - .q (), - .qs (meta_qs) - ); - - - - - logic [3:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == BUS_ERR_UNIT_ERR_ADDR_OFFSET); - addr_hit[1] = (reg_addr == BUS_ERR_UNIT_ERR_ADDR_TOP_OFFSET); - addr_hit[2] = (reg_addr == BUS_ERR_UNIT_ERR_CODE_OFFSET); - addr_hit[3] = (reg_addr == BUS_ERR_UNIT_META_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[0] & (|(BUS_ERR_UNIT_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(BUS_ERR_UNIT_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(BUS_ERR_UNIT_PERMIT[2] & ~reg_be))) | - (addr_hit[3] & (|(BUS_ERR_UNIT_PERMIT[3] & ~reg_be))))); - end - - assign err_addr_re = addr_hit[0] & reg_re & !reg_error; - - assign err_addr_top_re = addr_hit[1] & reg_re & !reg_error; - - assign err_code_re = addr_hit[2] & reg_re & !reg_error; - - assign meta_re = addr_hit[3] & reg_re & !reg_error; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[31:0] = err_addr_qs; - end - - addr_hit[1]: begin - reg_rdata_next[31:0] = err_addr_top_qs; - end - - addr_hit[2]: begin - reg_rdata_next[31:0] = err_code_qs; - end - - addr_hit[3]: begin - reg_rdata_next[31:0] = meta_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule - -module bus_err_unit_reg_top_intf -#( - parameter int AW = 4, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output bus_err_unit_reg_pkg::bus_err_unit_reg2hw_t reg2hw, // Write - input bus_err_unit_reg_pkg::bus_err_unit_hw2reg_t hw2reg, // Read - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - localparam int unsigned STRB_WIDTH = DW/8; - -`include "register_interface/typedef.svh" -`include "register_interface/assign.svh" - - // Define structs for reg_bus - typedef logic [AW-1:0] addr_t; - typedef logic [DW-1:0] data_t; - typedef logic [STRB_WIDTH-1:0] strb_t; - `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) - - reg_bus_req_t s_reg_req; - reg_bus_rsp_t s_reg_rsp; - - // Assign SV interface to structs - `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) - `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) - - - - bus_err_unit_reg_top #( - .reg_req_t(reg_bus_req_t), - .reg_rsp_t(reg_bus_rsp_t), - .AW(AW) - ) i_regs ( - .clk_i, - .rst_ni, - .reg_req_i(s_reg_req), - .reg_rsp_o(s_reg_rsp), - .reg2hw, // Write - .hw2reg, // Read - .devmode_i - ); - +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module bus_err_unit_reg_top ( + input wire clk, + input wire arst_n, + + input wire s_apb_psel, + input wire s_apb_penable, + input wire s_apb_pwrite, + input wire [2:0] s_apb_pprot, + input wire [3:0] s_apb_paddr, + input wire [31:0] s_apb_pwdata, + input wire [3:0] s_apb_pstrb, + output logic s_apb_pready, + output logic [31:0] s_apb_prdata, + output logic s_apb_pslverr, + + input bus_err_unit_reg_pkg::bus_err_unit__in_t hwif_in, + output bus_err_unit_reg_pkg::bus_err_unit__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [3:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + // Request + logic is_active; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + is_active <= '0; + cpuif_req <= '0; + cpuif_req_is_wr <= '0; + cpuif_addr <= '0; + cpuif_wr_data <= '0; + cpuif_wr_biten <= '0; + end else begin + if(~is_active) begin + if(s_apb_psel) begin + is_active <= '1; + cpuif_req <= '1; + cpuif_req_is_wr <= s_apb_pwrite; + cpuif_addr <= {s_apb_paddr[3:2], 2'b0}; + cpuif_wr_data <= s_apb_pwdata; + for(int i=0; i<4; i++) begin + cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}}; + end + end + end else begin + cpuif_req <= '0; + if(cpuif_rd_ack || cpuif_wr_ack) begin + is_active <= '0; + end + end + end + end + + // Response + assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack; + assign s_apb_prdata = cpuif_rd_data; + assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err; + + logic cpuif_req_masked; + logic external_req; + logic external_pending; + logic external_wr_ack; + logic external_rd_ack; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + external_pending <= '0; + end else begin + if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1; + else if(external_wr_ack | external_rd_ack) external_pending <= '0; + `ifndef SYNTHESIS + assert(!external_wr_ack || (external_pending | external_req)) + else $error("An external wr_ack strobe was asserted when no external request was active"); + assert(!external_rd_ack || (external_pending | external_req)) + else $error("An external rd_ack strobe was asserted when no external request was active"); + `endif + end + end + + // Read & write latencies are balanced. Stalls not required + // except if external + assign cpuif_req_stall_rd = external_pending; + assign cpuif_req_stall_wr = external_pending; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct { + logic err_addr; + logic err_addr_top; + logic err_code; + logic meta; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_strb_is_external; + + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + automatic logic is_external; + is_external = '0; + decoded_reg_strb.err_addr = cpuif_req_masked & (cpuif_addr == 4'h0); + is_external |= cpuif_req_masked & (cpuif_addr == 4'h0) & !cpuif_req_is_wr; + decoded_reg_strb.err_addr_top = cpuif_req_masked & (cpuif_addr == 4'h4); + is_external |= cpuif_req_masked & (cpuif_addr == 4'h4) & !cpuif_req_is_wr; + decoded_reg_strb.err_code = cpuif_req_masked & (cpuif_addr == 4'h8); + is_external |= cpuif_req_masked & (cpuif_addr == 4'h8) & !cpuif_req_is_wr; + decoded_reg_strb.meta = cpuif_req_masked & (cpuif_addr == 4'hc); + is_external |= cpuif_req_masked & (cpuif_addr == 4'hc) & !cpuif_req_is_wr; + decoded_strb_is_external = is_external; + external_req = is_external; + end + + // Pass down signals to next stage + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + + + + + + assign hwif_out.err_addr.req = !decoded_req_is_wr ? decoded_reg_strb.err_addr : '0; + assign hwif_out.err_addr.req_is_wr = decoded_req_is_wr; + + assign hwif_out.err_addr_top.req = !decoded_req_is_wr ? decoded_reg_strb.err_addr_top : '0; + assign hwif_out.err_addr_top.req_is_wr = decoded_req_is_wr; + + assign hwif_out.err_code.req = !decoded_req_is_wr ? decoded_reg_strb.err_code : '0; + assign hwif_out.err_code.req_is_wr = decoded_req_is_wr; + + assign hwif_out.meta.req = !decoded_req_is_wr ? decoded_reg_strb.meta : '0; + assign hwif_out.meta.req_is_wr = decoded_req_is_wr; + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + always_comb begin + automatic logic wr_ack; + wr_ack = '0; + + external_wr_ack = wr_ack; + end + assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external); + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + logic readback_external_rd_ack_c; + always_comb begin + automatic logic rd_ack; + rd_ack = '0; + rd_ack |= hwif_in.err_addr.rd_ack; + rd_ack |= hwif_in.err_addr_top.rd_ack; + rd_ack |= hwif_in.err_code.rd_ack; + rd_ack |= hwif_in.meta.rd_ack; + readback_external_rd_ack_c = rd_ack; + end + + logic readback_external_rd_ack; + + assign readback_external_rd_ack = readback_external_rd_ack_c; + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + + // Assign readback values to a flattened array + logic [31:0] readback_array[4]; + assign readback_array[0] = hwif_in.err_addr.rd_ack ? hwif_in.err_addr.rd_data : '0; + assign readback_array[1] = hwif_in.err_addr_top.rd_ack ? hwif_in.err_addr_top.rd_data : '0; + assign readback_array[2] = hwif_in.err_code.rd_ack ? hwif_in.err_code.rd_data : '0; + assign readback_array[3] = hwif_in.meta.rd_ack ? hwif_in.meta.rd_data : '0; + + // Reduce the array + always_comb begin + automatic logic [31:0] readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external; + readback_err = '0; + readback_data_var = '0; + for(int i=0; i<4; i++) readback_data_var |= readback_array[i]; + readback_data = readback_data_var; + end + + assign external_rd_ack = readback_external_rd_ack; + assign cpuif_rd_ack = readback_done | readback_external_rd_ack; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; endmodule - - diff --git a/src/err_unit_regs.hjson b/src/err_unit_regs.hjson deleted file mode 100644 index b5c2d3c..0000000 --- a/src/err_unit_regs.hjson +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Author: Michael Rogenmoser - -{ - name: "bus_err_unit", - clock_primary: "clk_i", - reset_primary: "rst_ni", - bus_interfaces: [ - { protocol: "reg_iface", - direction: "device" - } - ], - - regwidth: "32", - - registers: [ - { name: "err_addr", - desc: "Address of the bus error", - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "31:0", - name: "err_addr", - desc: "Address of the bus error" - } - ] - }, - { name: "err_addr_top", - desc: "Top of the address of the bus error", - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "31:0", - name: "err_addr", - desc: "Address of the bus error" - } - ] - }, - { name: "err_code", - desc: "Error code of the bus error", - swaccess: "ro", - hwaccess: "hrw", - hwext: "true", - hwre: "true", - fields: [ - { bits: "31:0", - name: "err_code", - desc: "Error code of the bus error" - } - ] - }, - { name: "meta", - desc: "Meta information of the bus error", - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "31:0", - name: "meta", - desc: "Meta information of the bus error" - } - ] - } - ] -} diff --git a/src/obi_err_unit_wrap.sv b/src/obi_err_unit_wrap.sv index 8075aa2..bec4d88 100644 --- a/src/obi_err_unit_wrap.sv +++ b/src/obi_err_unit_wrap.sv @@ -12,8 +12,8 @@ module obi_err_unit_wrap #( parameter int unsigned NumOutstanding = 2, parameter int unsigned NumStoredErrors = 1, parameter bit DropOldest = 1'b0, - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic + parameter type apb_req_t = logic, + parameter type apb_rsp_t = logic ) ( input logic clk_i, input logic rst_ni, @@ -28,8 +28,8 @@ module obi_err_unit_wrap #( output logic err_irq_o, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o + input apb_req_t apb_req_i, + output apb_rsp_t apb_rsp_o ); bus_err_unit #( @@ -40,8 +40,8 @@ module obi_err_unit_wrap #( .NumStoredErrors(NumStoredErrors), .NumChannels (1), .DropOldest (DropOldest), - .reg_req_t (reg_req_t), - .reg_rsp_t (reg_rsp_t) + .apb_req_t (apb_req_t), + .apb_rsp_t (apb_rsp_t) ) i_err_unit ( .clk_i, .rst_ni, @@ -56,8 +56,8 @@ module obi_err_unit_wrap #( .err_irq_o, - .reg_req_i, - .reg_rsp_o + .apb_req_i, + .apb_rsp_o ); endmodule