From b95ba354c3c0b4e525d26c4de0a28abffa7979d8 Mon Sep 17 00:00:00 2001 From: Alex Mykyta Date: Fri, 11 Apr 2025 21:14:15 -0700 Subject: [PATCH] Add simulation-time width assertions to SV interfaces. #128 --- src/peakrdl_regblock/cpuif/apb3/__init__.py | 3 +++ src/peakrdl_regblock/cpuif/apb3/apb3_tmpl.sv | 12 ++++++++++++ src/peakrdl_regblock/cpuif/apb4/__init__.py | 3 +++ src/peakrdl_regblock/cpuif/apb4/apb4_tmpl.sv | 12 ++++++++++++ src/peakrdl_regblock/cpuif/avalon/__init__.py | 3 +++ src/peakrdl_regblock/cpuif/avalon/avalon_tmpl.sv | 12 ++++++++++++ src/peakrdl_regblock/cpuif/axi4lite/__init__.py | 3 +++ src/peakrdl_regblock/cpuif/axi4lite/axi4lite_tmpl.sv | 12 ++++++++++++ src/peakrdl_regblock/cpuif/base.py | 1 + 9 files changed, 61 insertions(+) diff --git a/src/peakrdl_regblock/cpuif/apb3/__init__.py b/src/peakrdl_regblock/cpuif/apb3/__init__.py index 1b79ff0..4b1adc1 100644 --- a/src/peakrdl_regblock/cpuif/apb3/__init__.py +++ b/src/peakrdl_regblock/cpuif/apb3/__init__.py @@ -2,6 +2,7 @@ from ..base import CpuifBase class APB3_Cpuif(CpuifBase): template_path = "apb3_tmpl.sv" + is_interface = True @property def port_declaration(self) -> str: @@ -12,6 +13,8 @@ class APB3_Cpuif(CpuifBase): class APB3_Cpuif_flattened(APB3_Cpuif): + is_interface = False + @property def port_declaration(self) -> str: lines = [ diff --git a/src/peakrdl_regblock/cpuif/apb3/apb3_tmpl.sv b/src/peakrdl_regblock/cpuif/apb3/apb3_tmpl.sv index bcd45ea..4cc23af 100644 --- a/src/peakrdl_regblock/cpuif/apb3/apb3_tmpl.sv +++ b/src/peakrdl_regblock/cpuif/apb3/apb3_tmpl.sv @@ -1,3 +1,15 @@ +{%- if cpuif.is_interface -%} +`ifndef SYNTHESIS + initial begin + assert($bits({{cpuif.signal("paddr")}}) >= {{ds.package_name}}::{{ds.module_name.upper()}}_MIN_ADDR_WIDTH) + else $error("Interface address width of %0d is too small. Shall be at least %0d bits", $bits({{cpuif.signal("paddr")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_MIN_ADDR_WIDTH); + assert($bits({{cpuif.signal("pwdata")}}) == {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH) + else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits({{cpuif.signal("pwdata")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH); + end +`endif + +{% endif -%} + // Request logic is_active; always_ff {{get_always_ff_event(cpuif.reset)}} begin diff --git a/src/peakrdl_regblock/cpuif/apb4/__init__.py b/src/peakrdl_regblock/cpuif/apb4/__init__.py index a74ae49..45b2961 100644 --- a/src/peakrdl_regblock/cpuif/apb4/__init__.py +++ b/src/peakrdl_regblock/cpuif/apb4/__init__.py @@ -2,6 +2,7 @@ from ..base import CpuifBase class APB4_Cpuif(CpuifBase): template_path = "apb4_tmpl.sv" + is_interface = True @property def port_declaration(self) -> str: @@ -12,6 +13,8 @@ class APB4_Cpuif(CpuifBase): class APB4_Cpuif_flattened(APB4_Cpuif): + is_interface = False + @property def port_declaration(self) -> str: lines = [ diff --git a/src/peakrdl_regblock/cpuif/apb4/apb4_tmpl.sv b/src/peakrdl_regblock/cpuif/apb4/apb4_tmpl.sv index 34f51b6..0152aeb 100644 --- a/src/peakrdl_regblock/cpuif/apb4/apb4_tmpl.sv +++ b/src/peakrdl_regblock/cpuif/apb4/apb4_tmpl.sv @@ -1,3 +1,15 @@ +{%- if cpuif.is_interface -%} +`ifndef SYNTHESIS + initial begin + assert($bits({{cpuif.signal("paddr")}}) >= {{ds.package_name}}::{{ds.module_name.upper()}}_MIN_ADDR_WIDTH) + else $error("Interface address width of %0d is too small. Shall be at least %0d bits", $bits({{cpuif.signal("paddr")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_MIN_ADDR_WIDTH); + assert($bits({{cpuif.signal("pwdata")}}) == {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH) + else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits({{cpuif.signal("pwdata")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH); + end +`endif + +{% endif -%} + // Request logic is_active; always_ff {{get_always_ff_event(cpuif.reset)}} begin diff --git a/src/peakrdl_regblock/cpuif/avalon/__init__.py b/src/peakrdl_regblock/cpuif/avalon/__init__.py index aaed77d..20d8a59 100644 --- a/src/peakrdl_regblock/cpuif/avalon/__init__.py +++ b/src/peakrdl_regblock/cpuif/avalon/__init__.py @@ -3,6 +3,7 @@ from ...utils import clog2 class Avalon_Cpuif(CpuifBase): template_path = "avalon_tmpl.sv" + is_interface = True @property def port_declaration(self) -> str: @@ -17,6 +18,8 @@ class Avalon_Cpuif(CpuifBase): return self.addr_width - clog2(self.data_width_bytes) class Avalon_Cpuif_flattened(Avalon_Cpuif): + is_interface = False + @property def port_declaration(self) -> str: lines = [ diff --git a/src/peakrdl_regblock/cpuif/avalon/avalon_tmpl.sv b/src/peakrdl_regblock/cpuif/avalon/avalon_tmpl.sv index be7e1d0..da1bf34 100644 --- a/src/peakrdl_regblock/cpuif/avalon/avalon_tmpl.sv +++ b/src/peakrdl_regblock/cpuif/avalon/avalon_tmpl.sv @@ -1,3 +1,15 @@ +{%- if cpuif.is_interface -%} +`ifndef SYNTHESIS + initial begin + assert($bits({{cpuif.signal("address")}}) >= {{cpuif.word_addr_width}}) + else $error("Interface address width of %0d is too small. Shall be at least %0d bits", $bits({{cpuif.signal("address")}}), {{cpuif.word_addr_width}}); + assert($bits({{cpuif.signal("writedata")}}) == {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH) + else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits({{cpuif.signal("writedata")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH); + end +`endif + +{% endif -%} + // Request always_comb begin cpuif_req = {{cpuif.signal("read")}} | {{cpuif.signal("write")}}; diff --git a/src/peakrdl_regblock/cpuif/axi4lite/__init__.py b/src/peakrdl_regblock/cpuif/axi4lite/__init__.py index 31c3eb7..65dead5 100644 --- a/src/peakrdl_regblock/cpuif/axi4lite/__init__.py +++ b/src/peakrdl_regblock/cpuif/axi4lite/__init__.py @@ -2,6 +2,7 @@ from ..base import CpuifBase class AXI4Lite_Cpuif(CpuifBase): template_path = "axi4lite_tmpl.sv" + is_interface = True @property def port_declaration(self) -> str: @@ -34,6 +35,8 @@ class AXI4Lite_Cpuif(CpuifBase): class AXI4Lite_Cpuif_flattened(AXI4Lite_Cpuif): + is_interface = False + @property def port_declaration(self) -> str: lines = [ diff --git a/src/peakrdl_regblock/cpuif/axi4lite/axi4lite_tmpl.sv b/src/peakrdl_regblock/cpuif/axi4lite/axi4lite_tmpl.sv index 9adda66..a578718 100644 --- a/src/peakrdl_regblock/cpuif/axi4lite/axi4lite_tmpl.sv +++ b/src/peakrdl_regblock/cpuif/axi4lite/axi4lite_tmpl.sv @@ -1,3 +1,15 @@ +{%- if cpuif.is_interface -%} +`ifndef SYNTHESIS + initial begin + assert($bits({{cpuif.signal("araddr")}}) >= {{ds.package_name}}::{{ds.module_name.upper()}}_MIN_ADDR_WIDTH) + else $error("Interface address width of %0d is too small. Shall be at least %0d bits", $bits({{cpuif.signal("araddr")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_MIN_ADDR_WIDTH); + assert($bits({{cpuif.signal("wdata")}}) == {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH) + else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits({{cpuif.signal("wdata")}}), {{ds.package_name}}::{{ds.module_name.upper()}}_DATA_WIDTH); + end +`endif + +{% endif -%} + // Max Outstanding Transactions: {{cpuif.max_outstanding}} logic [{{clog2(cpuif.max_outstanding+1)-1}}:0] axil_n_in_flight; logic axil_prev_was_rd; diff --git a/src/peakrdl_regblock/cpuif/base.py b/src/peakrdl_regblock/cpuif/base.py index a9c43d0..2031a71 100644 --- a/src/peakrdl_regblock/cpuif/base.py +++ b/src/peakrdl_regblock/cpuif/base.py @@ -69,6 +69,7 @@ class CpuifBase: "clog2": clog2, "is_pow2": is_pow2, "roundup_pow2": roundup_pow2, + "ds": self.exp.ds, } template = jj_env.get_template(self.template_path)