From 7ba57f6f04fa6f7e6904692bc202485f0ac67d63 Mon Sep 17 00:00:00 2001 From: Serge Rabyking Date: Wed, 22 Apr 2026 13:09:37 +0200 Subject: [PATCH] docs: document RTL wrapper Verilog parameter support - rtl-wrapper.md: new "Verilog module parameters" section covering the TOML [parameters] table, Python-kwarg override precedence, p_* emission on Instance, and propagation into generator template substitution and [ports.*] params. - cv32e40p-example.md: add a [parameters] table demonstrating the new override path, and drop the stale "Parameters aren't set by the wrapper" caveat. Requires chipflow-lib PR #162. --- cv32e40p-example.md | 11 ++++++++++- rtl-wrapper.md | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/cv32e40p-example.md b/cv32e40p-example.md index 160b4f2..e805a7a 100644 --- a/cv32e40p-example.md +++ b/cv32e40p-example.md @@ -96,6 +96,16 @@ generator = "systemverilog" # preprocess with sv2v include_dirs = ["./cv32e40p/rtl/include"] top_module = "cv32e40p_core" +# Verilog module parameter overrides — emitted as p_ on the Instance. +# Override any of these from Python via +# `load_wrapper_from_toml("cv32e40p.toml", parameters={"FPU": 1})`. +[parameters] +COREV_PULP = 0 +COREV_CLUSTER = 0 +FPU = 0 # keep 0 to avoid pulling in the FPU wrapper +ZFINX = 0 +NUM_MHPMCOUNTERS = 1 + [clocks] sys = "clk_i" # wrapper generates i_clk_i = ClockSignal() @@ -241,7 +251,6 @@ MySoC = MySoC ## Caveats -- **Parameters aren't set by the wrapper.** CV32E40P uses its module defaults (`FPU = 0`, `COREV_PULP = 0`, `COREV_CLUSTER = 0`). If you need different values, you'd either need to extend the wrapper or add an `Instance(..., p_FPU=1, ...)` manually. - **All module ports must appear in `map`.** Unmapped ports will not be connected (the wrapper only wires what you listed). - **APU/FPU ports exist even when `FPU = 0`** — they must still be wired or tied off. If you don't need the FPU, tie `apu_gnt_i = 0`, `apu_rvalid_i = 0`, `apu_result_i = 0`, `apu_flags_i = 0` in your design and leave the output APU signals unconnected (they'll be driven but go nowhere). - **Debug interface:** tie `debug_req_i = 0` and ignore `debug_*_o` outputs unless you're wiring up a JTAG debug transport. diff --git a/rtl-wrapper.md b/rtl-wrapper.md index 092c20b..2abe927 100644 --- a/rtl-wrapper.md +++ b/rtl-wrapper.md @@ -135,6 +135,29 @@ Auto-mapping is built in for these interfaces — the wrapper parses the Verilog For other interfaces, or when the Verilog uses non-standard names, provide an explicit `map` in TOML. +## Verilog module parameters + +Verilog `parameter` / `localparam` values can be overridden from TOML, from Python, or both. Declare defaults in the TOML `[parameters]` table: + +```toml +name = "wb_timer" + +[parameters] +DATA_WIDTH = 32 +ADDR_WIDTH = 4 +``` + +At load time, pass a `parameters=` kwarg to override specific values. The Python kwarg wins on collisions; parameters you don't mention fall back to the TOML defaults: + +```python +# DATA_WIDTH=64 (override), ADDR_WIDTH=4 (TOML default) +timer = load_wrapper_from_toml("wb_timer.toml", parameters={"DATA_WIDTH": 64}) +``` + +The merged set is emitted as `p_=` kwargs on the `Instance(...)` at elaboration — equivalent to `Instance("wb_timer", p_DATA_WIDTH=64, p_ADDR_WIDTH=4, …)`. + +When a `[generate]` section is present, the merged parameters are also fed into the generator's template substitution, so SpinalHDL Scala args, sv2v `-D` defines, and yosys-slang `-D` / `--top` placeholders all see the final values. The same `{name}` substitution works in `[ports.*] params = { … }` — writing `params = { addr_width = "{ADDR_WIDTH}" }` resolves against the merged parameters. + ## Preprocessing SystemVerilog sources If your external RTL is SystemVerilog that uses packages/interfaces/typedefs, add a `[generate]` section to preprocess it: