feat: refactor RTL code for improved readability and style compliance

- Updated multiple modules to enhance code formatting and readability by breaking long lines and aligning conditions.
- Improved comments for clarity in , , and .
- Added checks in  to reject forbidden constructs such as , non-ASCII characters, and lines exceeding 100 characters.
- Introduced unit tests to validate style checks for forbidden constructs and non-ASCII characters.
This commit is contained in:
maksyuki committed 2026-08-13 09:53:59 +08:00
1 parent 628b5a5320
commit cf30a81c24
13 files changed
+326 -188

No files matched your search

+3
View File
@@ -58,6 +58,9 @@ jobs:
- name: Check source formatting
run: make format-check
- name: Check all self-owned RTL style rules
run: make rtl-style-check-all
- name: Check embedded C safety policy
run: make sw-policy-check
+8 -2
View File
@@ -262,7 +262,8 @@ endif
benchmark-report coremark-report \
pin-map check-pin-map soc-topology check-soc-topology user-extensions check-user-extensions \
check-clock-reset-domains tech-cell-test rtl-lint check-rtl-lint \
formal formal-bus formal-rib-adapter formal-rib2apb formal-gpio formal-ws2812 formal-uart formal-i2c formal-timer formal-dvp formal-clean formal-doctor
formal formal-bus formal-rib-adapter formal-rib2apb formal-gpio formal-ws2812 formal-uart formal-i2c formal-timer formal-dvp formal-clean formal-doctor \
rtl-style-check-all
.NOTPARALLEL: setup
help:
@@ -303,6 +304,7 @@ help:
' sw-format-check check embedded C whitespace and line-ending policy' \
' mk-format | mk-format-check apply/check tracked Makefile formatting' \
' rtl-format | rtl-format-check apply/check self-owned RTL formatting' \
' rtl-style-check-all check all self-owned RTL naming and language rules' \
' rtl-migrate-connections convert provably positional RTL instances to named ports' \
' rtl-migrate-names shorten local RTL identifier names' \
' rtl-style-check check changed self-owned RTL naming and connections' \
@@ -439,6 +441,10 @@ rtl-style-check:
python3 $(ROOT_PATH)/scripts/check_rtl_style.py --root $(ROOT_PATH) \
--profile owned --changed-only --verible-verilog-lint $(VERIBLE_LINT)
rtl-style-check-all:
python3 $(ROOT_PATH)/scripts/check_rtl_style.py --root $(ROOT_PATH) \
--profile owned --verible-verilog-lint $(VERIBLE_LINT)
sw-policy-check:
python3 $(ROOT_PATH)/scripts/check_embedded_c.py --root $(ROOT_PATH) --policy-check
@@ -462,4 +468,4 @@ regress-nightly:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite nightly
sim-asm: asm
$(MAKE) SIM_FIRMWARE_NAME=$(ASM_FIRMWARE_NAME) sim
$(MAKE) SIM_FIRMWARE_NAME=$(ASM_FIRMWARE_NAME) sim
+154 -138
View File
@@ -1,21 +1,70 @@
# retroSoC RTL Coding Style
This document is the source of truth for self-owned RTL coding and formatting.
It applies to `rtl/ip/**` and `rtl/mini/top/**`. Formal, device-model, PDK,
generated, and third-party sources use the profiles declared in
[`rtl/rtl_style_manifest.json`](../rtl/rtl_style_manifest.json).
It follows the restricted SystemVerilog guidance used by
[lowRISC](https://github.com/lowRISC/style-guides/blob/master/VerilogCodingStyle.md)
and the staged lint, assertion, CDC, and delivery methodology described by
[OpenTitan](https://opentitan.org/earlgrey_1.0.0/book/doc/contributing/hw/methodology.html).
Repository-specific rules in this document take precedence where conventions
differ: retroSoC uses `clk_i` and `rst_n_i`, not `rst_ni`.
## Naming
## 1. Scope and rule levels
Use `clk_i` and `rst_n_i` for clock and active-low reset ports. Do not rename
the reset to `rst_ni`. Use `_i`, `_o`, and `_io` for input, output, and
bidirectional ports; `s_` for local signals; and `u_` for instances. A state
register has adjacent `s_<name>_d` and `s_<name>_q` signals, with
`s_<name>_en` for a write enable.
The owned profile applies to `rtl/ip/**` and `rtl/mini/top/**`. Formal,
device-model, PDK, generated, managed, and third-party sources use the profiles
declared in [`rtl/rtl_style_manifest.json`](../rtl/rtl_style_manifest.json).
New local signals use concise industry-standard abbreviations:
The following terms are normative:
| Long form | RTL form |
- **MUST** and **MUST NOT** are blocking requirements.
- **SHOULD** and **SHOULD NOT** require review when not followed.
- **MAY** is optional when the interface and tool flow support it.
Style exceptions MUST be narrow, documented beside the code, and represented by
a reviewed waiver when the checker supports one. A waiver records the reason,
owner, affected path, related issue or commit, and an expiry or removal plan.
## 2. File and module boundaries
- Use SystemVerilog-2017 for owned RTL and tests, subject to the prohibited
constructs in this document.
- `.sv` files are compilation units. `.svh` files are include-only headers.
- A self-owned `.sv` file contains one primary module or one related package;
the file name and primary module name match in lower snake case.
- Do not combine unrelated modules to avoid filelist or dependency work.
- Do not edit `rtl/managed`, generated MPW output, vendored CPU sources, or
PDK cell definitions under the owned profile. Update those through their
locked setup flow.
## 3. Restricted SystemVerilog subset
Synthesizable owned RTL MUST NOT use:
- `#delay`, including `#0`, task declarations, or simulator timing controls;
- implicit nets, `defparam`, positional parameter or port connections, or `.*`;
- hierarchical references to implementation signals;
- `casex`, `full_case`, or `parallel_case` pragmas;
- `initial` blocks for synthesizable state.
Use `unique case` when uniqueness is part of the design contract and always
provide a `default` branch. Use `case`, `case inside`, or `casez` only when the
wildcard behavior is intentional; never use `casex` in owned RTL.
Synthesizable functions MUST be `automatic`, use explicitly typed arguments and
return values, and only consume inputs to produce one result. Tasks are
reserved for verification code.
## 4. Naming, types, and packages
Use `lower_snake_case` for signals, ports, instances, functions, and modules.
Use `clk_i`, `rst_n_i`, `_i`, `_o`, and `_io` for ports; `s_` for local signals;
`u_` for instances; and adjacent `s_<name>_d`/`s_<name>_q` for state. A state
write enable is `s_<name>_en`.
Public interfaces, protocol fields, register fields, and technology pins keep
their required names. Local signals MAY use only approved concise aliases:
| Long form | Local form |
| --- | --- |
| command | `cmd` |
| request | `req` |
@@ -25,166 +74,133 @@ New local signals use concise industry-standard abbreviations:
| error | `err` |
| status | `stat` |
| counter | `cnt` |
| configuration | `cfg` |
| configuration/config | `cfg` |
| source | `src` |
| destination | `dst` |
| event | `evt` |
| target | `tgt` |
| select | `sel` |
| length | `len` |
Do not change an external protocol field only to shorten its name. Use a local
alias at the boundary when a legacy or third-party interface uses a long name.
New abbreviations require review and an update to `rtl/rtl_style_manifest.json`.
Use `_t` for typedefs, `_e` for enum types, `ALL_CAPS` for macros, and the
repository's established parameter naming convention.
The checked-in [`scripts/migrate_rtl_names.py`](../scripts/migrate_rtl_names.py)
helper applies this rule mechanically: it shortens only `s_`/`r_` locals and
known automatic variables, never a public port or interface member.
Declare explicit widths and signedness for parameters, ports, constants, and
internal signals. Use sized literals such as `8'h00` and `16'd42`. Do not rely
on implicit truncation, extension, unsized arithmetic, or signed conversion.
Cross-module shared typedefs, enums, and protocol constants belong in a
versioned package; module-private values use `localparam`. Avoid unqualified
`import pkg::*` across IP boundaries.
## Source and Module Boundaries
## 5. Module structure and structural connections
Keep one self-owned SystemVerilog module per source file. The file name and the
primary module name must match, including case. This keeps filelists,
dependency tracking, lint diagnostics, and synthesis reports unambiguous. A
small set of closely related declarations may remain in a shared package or
interface file when that is the established repository pattern; do not use a
multi-module source file as a shortcut for unrelated hierarchy.
Order a module as: header, parameters, ports, localparams, internal signals,
interface/structural assignments, combinational logic, sequential logic,
instances, and assertions. Declare every signal before executable code.
SystemVerilog is case-sensitive. Use lower snake case consistently and do not
create identifiers that differ only by capitalization. Every public interface
member and technology-facing pin keeps the spelling required by its protocol
or PDK; local aliases may use the concise naming rules above.
Use structural HDL for hierarchy and named interconnections. Every owned
instance MUST use named parameter and port connections. Unused inputs MUST be
tied to an explicit value; unused outputs MAY use an empty named connection
only with a comment explaining it. Every synthesizable signal has one driver.
## Types, Widths, and Operators
Use `logic` for ordinary synthesizable signals. Reserve `wire` for resolved
multi-driver nets, pads, tri-state buses, or technology models, and document the
net semantics. Do not use on-chip tri-state logic to implement a mux.
Declare the width and signedness of constants, parameters, ports, and internal
signals explicitly. The left and right sides of an assignment should have the
same intended width; do not rely on implicit truncation, extension, or signed
conversion. Use sized literals with a visible base, for example `8'h00`,
`16'd42`, or `4'b0011`, and use underscores only to improve readability.
Every `generate` if/else branch and for-loop MUST have a lower-snake-case label
so that hierarchy is stable across tools and configurations.
Keep bitwise and logical operators distinct. Use `~`, `&`, `|`, and `^` for
vector or bit-level hardware operations. Use `!`, `&&`, and `||` for Boolean
conditions and predicates. Parenthesize mixed-width arithmetic and mixed
operator expressions when precedence is not immediately obvious.
## 6. Combinational logic, registers, and FSMs
Use `logic` for ordinary synthesizable signals. Reserve `wire` for signals
whose net semantics are required, such as resolved multi-driver nets,
tri-state buses, PDK pads, or technology models. A synthesizable signal must
have one driver: do not assign the same signal from multiple processes, a
process and a continuous assignment, or multiple continuous assignments.
Use `always_comb` for procedural combinational logic and `always_ff` for
sequential logic. Use blocking assignments in combinational blocks and
non-blocking assignments in sequential blocks. Prefer continuous assignments
for simple wiring and muxes.
## Structure
Every combinational block assigns defaults to all outputs and next-state
signals. A sequential block contains reset behavior, explicit enable/update
conditions, and assignments of already-computed next-state values. Do not put
large datapaths or unrelated decode inside a flip-flop process.
Keep each module in this order: module header, parameters, ports, localparams,
internal declarations, combinational next-state logic, sequential logic,
instances, and assertions. Use `logic` for synthesizable data and state. Use
`wire` only where net resolution is required, such as PDK pads, tri-state
signals, and technology models.
Describe each register as an adjacent pair: input/next-state combinational
logic followed by a ClusterIP Common register primitive such as `dffr`,
`dffer`, `dffrc`, or `dfferc`. Enables MUST be visible in the selected primitive
or next-state condition.
Keep control logic and datapath logic in the same module when they are tightly
coupled and expected to evolve together. Use hierarchy to divide independent
functions, share a reusable implementation, isolate a clock/reset domain, or
give separate teams and tools a clear ownership boundary. Do not introduce a
control-only or datapath-only wrapper solely to move a handful of signals.
Describe FSMs with `typedef enum logic`, `state_d/state_q`, a combinational
decode block, and a clocked state register. Include an explicit illegal-state
recovery branch. Moore outputs depend on state; Mealy outputs document their
input-dependent timing.
Use `always_ff` for sequential logic and `always_comb` for combinational logic.
Give every combinational block complete defaults and every `case` statement an
explicit `default`. Reuse the ClusterIP Common register cells (`dffr`, `dffer`,
`dffrc`, `dfferc`, and related variants) for local state. Do not add
`initial`-based synthesizable state.
## 7. Widths, operators, and invalid values
Use blocking assignments (`=`) in `always_comb` and non-blocking assignments
(`<=`) in `always_ff`. Use `always_latch` only when level-sensitive storage is
an intentional architectural requirement; latches are otherwise avoided in
self-owned SoC RTL. Prefer a continuous assignment for a simple Boolean or
multiplexer expression instead of a process with a manually maintained
sensitivity list.
Do not use a multi-bit vector directly as a Boolean condition. Write an
explicit comparison such as `value != '0`, a reduction operator, or a bit
select. Use bitwise operators (`~`, `&`, `|`, `^`) for data and logical
operators (`!`, `&&`, `||`) for predicates. Parenthesize mixed-width or mixed
signedness expressions and use explicit casts where needed.
Every combinational process must assign a default to each output and next-state
signal before conditional logic. Every sequential process must describe a
reset value and then update only the present-state registers it owns. An
enable or condition should gate an update, not create an accidental clock or
partial assignment. These rules make inferred storage and clock-enable intent
visible to lint, synthesis, and review.
`X` is unknown/conflicting simulation information, not ordinary synthesizable
data. Do not assign `X` to hide an uninitialized register, illegal state, or
unhandled case. Use deterministic safe behavior and SVA to detect invalid
usage. `Z` is limited to pads, intentional tri-state interfaces, and technology
models. Guard dynamic array indices when an out-of-range value could be
observed.
Every module instance in self-owned RTL must use named parameter and port
connections. Empty connections are permitted only for intentionally unused
technology pins or interface fields and must be documented.
## 8. Clock, reset, CDC, and protocol contracts
For existing positional instances, use the conservative
[`scripts/migrate_rtl_connections.py`](../scripts/migrate_rtl_connections.py)
helper. It only changes an instance when the declaration and argument counts
are unambiguous. Instances it reports as ambiguous require manual conversion;
the helper never guesses across duplicate or non-ANSI module declarations.
The default domain uses `clk_i` and `rst_n_i`. Additional domains use a stable
qualified form such as `clk_axi_i` and `rst_axi_n_i`. Every CDC crossing records
source domain, destination domain, reset assumptions, and the approved
synchronizer, handshake, or asynchronous FIFO primitive.
## State Machines and RTL Architecture
Each bus or streaming interface documents acceptance, backpressure, response
error behavior, reset values, and outstanding-transaction limits. RIB/RIBP and
AXI adapters MUST make burst boundaries, response timing, and access permissions
explicit at the module boundary.
Represent finite-state-machine states with a named `typedef enum logic` when
the state encoding is not itself a public protocol. Maintain paired
`state_d`/`state_q` signals, initialize `state_d` from `state_q`, and include a
`default` branch that recovers from an illegal encoding. Moore outputs should
depend on state only; Mealy outputs may additionally depend on current inputs
and must document any timing consequence.
## 9. Assertions, formal, and IP readiness
Before implementing a non-trivial block, document a clean architecture,
signal-level block diagram, clock/reset domains, and an FSM transition diagram
where applicable. RTL is a clocked transfer of present state through
combinational logic into next state; make cycle boundaries, handshakes, and
backpressure explicit rather than relying on simulator scheduling behavior.
Self-owned IP SHOULD include SVA for reset release, handshakes, FIFO bounds,
mutual exclusion, legal FSM states, and register access permissions. Formal and
testbench-only constructs use the verification profile and do not weaken the
synthesizable profile.
Keep datapath operations and control decisions conceptually separate even when
they share a module. Control should generate enables and selects, while the
datapath performs arithmetic, comparison, storage, and multiplexing. Avoid
placing large arithmetic datapaths inside deeply nested FSM conditionals unless
the resulting timing and resource intent is deliberate.
An IP is `verified` only when it has interface and register documentation,
clock/reset and CDC notes, architecture/FSM diagrams, simulation and formal
results, lint/format results, and an affected synthesis/STA result. A
`tapeout-ready` label additionally requires reviewed warnings, filelists, PDK
mapping, and release artifacts.
Use `begin`/`end` for multi-statement branches, nested branches, and branches
whose body may grow during maintenance. Keep indentation consistent and do
not rely on a single-line branch for safety-critical state updates.
## 10. Formatting, comments, and tools
## Comments and Intent
Owned RTL uses ASCII, Unix line endings, a 100-column limit, spaces instead of
tabs, no trailing whitespace, and a final newline in every non-empty file.
Use the root [`.verible-format`](../.verible-format) configuration. A narrow
`verilog_format: off/on` region is allowed only when the formatter cannot keep
required macro or port alignment; manually align it and explain the exception.
Use `//` comments for short intent statements. Comments should explain the
interface contract, cycle timing, reset assumptions, CDC rationale, ownership
of a signal, or a non-obvious synthesis constraint. Do not narrate syntax or
duplicate the code. Keep comments next to the rule they justify, especially
around `verilog_format: off/on`, intentional empty connections, tri-state
drivers, and lint waivers.
Use `//` comments for interface behavior, cycle timing, reset, CDC, ownership,
synthesis intent, or non-obvious constraints. Do not narrate syntax.
## Formatting
Run:
Run the following checks locally:
```sh
make rtl-format-check
make rtl-style-check
make rtl-lint
```
The root [`.verible-format`](../.verible-format) enables alignment for module
ports, named ports/parameters, declarations, assignments, case items, macros,
and struct members. `.svh` macro definitions and `.sv` module ports are kept in
columns. If Verible cannot preserve a required table, use a narrow region:
```systemverilog
// verilog_format: off
...
// verilog_format: on
```
Manually align every existing exception and add a comment explaining why the
exception is needed. Do not wrap an entire module in `format off`.
## Ownership boundaries
Do not hand-format or rename files below `rtl/managed`, generated MPW output,
or vendored CPU sources. Update those inputs through their locked setup flow.
PDK wrappers in `rtl/tech` preserve cell pin names and net semantics; they are
compiled and elaborated but are not subjected to the self-owned naming rules.
Formal properties and testbench models are checked with a verification profile
that permits bind-time wires and simulator-only constructs.
`rtl-style-check` checks changed owned RTL. `rtl-style-check-all` checks all
owned RTL and is used by nightly/release flows. Verilator performs semantic
linting for width, signedness, implicit conversion, and driven-signal issues;
Verible performs style linting. Fix findings before waiving them, and review
every waiver in the pull request.
## Reference
These practices are distilled from the ETH Zürich VLSI RTL lecture,
[`02_RTL.pdf`](https://vlsi.ethz.ch/w/images/d/de/02_RTL.pdf), including its
guidance on one module per file, explicit widths, single-driver signals,
intent-specific `always_*` processes, `_d`/`_q` state naming, enumerated FSMs,
and architecture-first RTL design. The repository-specific rules in this
document take precedence where the lecture uses different conventions, such
as `rst_ni` or `_c`; retroSoC continues to require `rst_n_i` and `clk_i`.
These rules also incorporate the architecture-first RTL guidance in the
[ETH Zürich VLSI RTL lecture](https://vlsi.ethz.ch/w/images/d/de/02_RTL.pdf).
The retroSoC naming and Common register rules above override examples in that
lecture where the project intentionally uses different conventions.
+6 -3
View File
@@ -145,21 +145,24 @@ module ribp_psram (
// wait cycles(mmio)
always_ff @(posedge clk_i, negedge rst_n_i) begin
if (~rst_n_i) r_cfg_wait <= 5'd18;
else if (ribp.valid && ribp.wstrb[0] && s_cfg_reg_sel && ribp.addr[7:0] == `RIBP_PSRAM_WAIT) begin
else if (ribp.valid && ribp.wstrb[0] && s_cfg_reg_sel &&
(ribp.addr[7:0] == `RIBP_PSRAM_WAIT)) begin
r_cfg_wait <= ribp.wdata[4:0];
end
end
// extra cycle for tCHD(mmio)
always_ff @(posedge clk_i, negedge rst_n_i) begin
if (~rst_n_i) r_cfg_chd <= 3'd4;
else if (ribp.valid && ribp.wstrb[0] && s_cfg_reg_sel && ribp.addr[7:0] == `RIBP_PSRAM_CHD) begin
else if (ribp.valid && ribp.wstrb[0] && s_cfg_reg_sel &&
(ribp.addr[7:0] == `RIBP_PSRAM_CHD)) begin
r_cfg_chd <= ribp.wdata[2:0];
end
end
// init device/switch qpi mode
always_ff @(posedge clk_i, negedge rst_n_i) begin
if (~rst_n_i) r_cfg_init <= '0;
else if (ribp.valid && ribp.wstrb[0] && s_cfg_reg_sel && ribp.addr[7:0] == `RIBP_PSRAM_INIT) begin
else if (ribp.valid && ribp.wstrb[0] && s_cfg_reg_sel &&
(ribp.addr[7:0] == `RIBP_PSRAM_INIT)) begin
r_cfg_init <= ribp.wdata[0];
end
end
+4 -3
View File
@@ -91,9 +91,10 @@ module psram_core (
psram_mosi_o = r_xfer_ca[31];
{psram_sio3_o, psram_sio2_o, psram_miso_o} = 3'd0;
end else begin // qpi mode
{psram_sio3_o, psram_sio2_o, psram_miso_o, psram_mosi_o} = r_fsm_state == FSM_WR_QPI ?
{r_xfer_byte_data[7], r_xfer_byte_data[6], r_xfer_byte_data[5], r_xfer_byte_data[4]} :
{r_xfer_ca[31], r_xfer_ca[30], r_xfer_ca[29], r_xfer_ca[28]};
{psram_sio3_o, psram_sio2_o, psram_miso_o, psram_mosi_o} =
r_fsm_state == FSM_WR_QPI
? {r_xfer_byte_data[7:4]}
: {r_xfer_ca[31], r_xfer_ca[30], r_xfer_ca[29], r_xfer_ca[28]};
end
end else begin
{psram_sio3_o, psram_sio2_o, psram_miso_o, psram_mosi_o} = 4'd0;
+1 -1
View File
@@ -135,7 +135,7 @@ module sdram_core (
logic s_cke_q, s_cke_d;
logic [12:0] s_addr_d, s_addr_q;
logic s_upd_ready_d, s_upd_ready_q;
// Registered RIB inputs (captured at IDLE→ACT)
// Registered RIB inputs (captured at IDLE-to-ACT)
logic [24:0] s_ribp_addr_d, s_ribp_addr_q; // addr[24:0] (relevant bits)
logic [31:0] s_ribp_wdata_d, s_ribp_wdata_q;
logic [3:0] s_ribp_wstrb_d, s_ribp_wstrb_q;
+4 -1
View File
@@ -266,7 +266,10 @@ module dvp_reg (
if (s_accept && s_write && !s_access_err && (s_offset == `RIBP_DVP_COMMAND)) begin
s_cmd_q <= s_cmd_q | ribp.wdata[1:0];
end
s_err_q <= (s_err_q | error_flags_i) & ~((s_accept && s_write && (s_offset == `RIBP_DVP_ERROR_STATUS)) ? ribp.wdata[5:0] : 6'd0);
s_err_q <= (s_err_q | error_flags_i) &
~((s_accept && s_write && (s_offset == `RIBP_DVP_ERROR_STATUS))
? ribp.wdata[5:0]
: 6'd0);
if (frame_start_i) s_intr_stat_q[`DVP_INTR_FRAME_START] <= 1'b1;
if (line_done_i) s_intr_stat_q[`DVP_INTR_LINE_DONE] <= 1'b1;
if (frame_done_i) s_intr_stat_q[`DVP_INTR_FRAME_DONE] <= 1'b1;
+18 -9
View File
@@ -78,14 +78,21 @@ module ribp_sysctrl (
typedef logic [7:0] sysctrl_offset_t;
localparam sysctrl_offset_t SYSCTRL_CORESEL_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_CORESEL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_CORESEL_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_CORESEL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_IPSEL_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_IPSEL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_CFG_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PLL_CFG_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_CMD_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PLL_CMD_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_STATUS_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_STATUS_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_ADDR_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_ADDR_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_COUNT_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_COUNT_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_STATUS_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PLL_STATUS_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_CFG_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PLL_CFG_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_CMD_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PLL_CMD_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_STATUS_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_STATUS_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_ADDR_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_ADDR_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_COUNT_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_COUNT_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_STATUS_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PLL_STATUS_OFFSET);
localparam sysctrl_offset_t SYSCTRL_USER_CORE_RESET_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_USER_CORE_RESET_OFFSET);
localparam sysctrl_offset_t SYSCTRL_USER_CORE_STATUS_OFFSET =
@@ -94,7 +101,8 @@ module ribp_sysctrl (
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_MASTER_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_DETAIL_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_DETAIL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_CTRL_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PERF_CTRL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_CTRL_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_CTRL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_MGMT_WAIT_HI_OFFSET =
@@ -343,7 +351,8 @@ module ribp_sysctrl (
.dat_o (s_sysctrl_ipsel_q)
);
assign s_pll_cfg_en = s_ribp_wr_hdshk && ribp.addr[7:0] == SYSCTRL_PLL_CFG_OFFSET && ribp.wstrb[0];
assign s_pll_cfg_en = s_ribp_wr_hdshk &&
(ribp.addr[7:0] == SYSCTRL_PLL_CFG_OFFSET) && ribp.wstrb[0];
assign s_pll_cfg_d = ribp.wdata[2:0];
dffer #(
.DATA_WIDTH(3)
+1 -1
View File
@@ -48,7 +48,7 @@ module spisd_init (
logic [6:0] s_boot_cnt_d, s_boot_cnt_q; // count 128
logic [2:0] s_fsm_d, s_fsm_q;
logic s_fir_clk_edge, s_sec_clk_edge;
// resp
// Response signals.
logic r_resp_en;
logic [47:0] r_resp_data;
logic r_resp_flag;
+53 -26
View File
@@ -240,7 +240,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ACCMD_BLOCK
assign s_xpi_accmd_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ACCMD && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_accmd_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ACCMD) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_accmd_d[i] = ribp.wdata[0];
end
dfferm #(
@@ -258,7 +259,8 @@ module xpi_reg (
// 5000_0000 - 5FFF_FFFF
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_MMSTAD_BLOCK
assign s_xpi_mmstad_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_MMSTAD && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_mmstad_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_MMSTAD) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
always_comb begin
s_xpi_mmstad_d[i] = s_xpi_mmstad_q[i];
if (ribp.wstrb[0]) s_xpi_mmstad_d[i][7:0] = ribp.wdata[7:0];
@@ -281,7 +283,9 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_MMOFFST_BLOCK
assign s_xpi_mmoffst_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_MMOFFST && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_mmoffst_en[i] = s_ribp_wr_hdshk &&
(ribp.addr[7:0] == `RIBP_XPI_MMOFFST) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
always_comb begin
s_xpi_mmoffst_d[i] = s_xpi_mmoffst_q[i];
if (ribp.wstrb[0]) s_xpi_mmoffst_d[i][7:0] = ribp.wdata[7:0];
@@ -304,7 +308,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_MODE_BLOCK
assign s_xpi_mode_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_MODE && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_mode_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_MODE) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_mode_d[i] = ribp.wdata[0];
end
dfferm #(
@@ -334,7 +339,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_CLKDIV_BLOCK
assign s_xpi_clkdiv_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_CLKDIV && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_clkdiv_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_CLKDIV) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_clkdiv_d[i] = ribp.wdata[7:0];
end
dfferm #(
@@ -351,7 +357,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_RDWR_BLOCK
assign s_xpi_rdwr_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_RDWR && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_rdwr_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_RDWR) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_rdwr_d[i] = ribp.wdata[0];
end
dfferm #(
@@ -368,7 +375,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_REVDAT_BLOCK
assign s_xpi_revdat_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_REVDAT && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_revdat_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_REVDAT) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_revdat_d[i] = ribp.wdata[0];
end
dfferm #(
@@ -385,7 +393,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_TXUPB_BLOCK
assign s_xpi_txupb_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_TXUPB && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_txupb_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_TXUPB) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_txupb_d[i] = ribp.wdata[7:0];
end
dfferm #(
@@ -402,7 +411,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_TXLOWB_BLOCK
assign s_xpi_txlowb_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_TXLOWB && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_txlowb_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_TXLOWB) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_txlowb_d[i] = ribp.wdata[7:0];
end
dfferm #(
@@ -419,7 +429,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_RXUPB_BLOCK
assign s_xpi_rxupb_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_RXUPB && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_rxupb_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_RXUPB) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_rxupb_d[i] = ribp.wdata[5:0];
end
dfferm #(
@@ -436,7 +447,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_RXLOWB_BLOCK
assign s_xpi_rxlowb_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_RXLOWB && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_rxlowb_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_RXLOWB) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_rxlowb_d[i] = ribp.wdata[5:0];
end
dfferm #(
@@ -457,7 +469,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_CMDTYP_BLOCK
assign s_xpi_cmdtyp_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_CMDTYP && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_cmdtyp_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_CMDTYP) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_cmdtyp_d[i] = ribp.wdata[1:0];
end
dfferm #(
@@ -474,7 +487,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_CMDLEN_BLOCK
assign s_xpi_cmdlen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_CMDLEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_cmdlen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_CMDLEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_cmdlen_d[i] = ribp.wdata[2:0];
end
dfferm #(
@@ -491,7 +505,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_CMDDAT_BLOCK
assign s_xpi_cmddat_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_CMDDAT && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_cmddat_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_CMDDAT) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
always_comb begin
s_xpi_cmddat_d[i] = s_xpi_cmddat_q[i];
if (ribp.wstrb[0]) s_xpi_cmddat_d[i][7:0] = ribp.wdata[7:0];
@@ -514,7 +529,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ADRTYP_BLOCK
assign s_xpi_adrtyp_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ADRTYP && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_adrtyp_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ADRTYP) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_adrtyp_d[i] = ribp.wdata[1:0];
end
dfferm #(
@@ -531,7 +547,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ADRLEN_BLOCK
assign s_xpi_adrlen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ADRLEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_adrlen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ADRLEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_adrlen_d[i] = ribp.wdata[2:0];
end
dfferm #(
@@ -548,7 +565,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ADRDAT_BLOCK
assign s_xpi_adrdat_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ADRDAT && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_adrdat_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ADRDAT) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
always_comb begin
s_xpi_adrdat_d[i] = s_xpi_adrdat_q[i];
if (ribp.wstrb[0]) s_xpi_adrdat_d[i][7:0] = ribp.wdata[7:0];
@@ -571,7 +589,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ALTTYP_BLOCK
assign s_xpi_alttyp_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ALTTYP && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_alttyp_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ALTTYP) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_alttyp_d[i] = ribp.wdata[1:0];
end
dfferm #(
@@ -588,7 +607,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ALTLEN_BLOCK
assign s_xpi_altlen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ALTLEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_altlen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ALTLEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_altlen_d[i] = ribp.wdata[2:0];
end
dfferm #(
@@ -605,7 +625,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_ALTDAT_BLOCK
assign s_xpi_altdat_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_ALTDAT && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_altdat_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_ALTDAT) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
always_comb begin
s_xpi_altdat_d[i] = s_xpi_altdat_q[i];
if (ribp.wstrb[0]) s_xpi_altdat_d[i][7:0] = ribp.wdata[7:0];
@@ -628,7 +649,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_TDULEN_BLOCK
assign s_xpi_tdulen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_TDULEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_tdulen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_TDULEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_tdulen_d[i] = ribp.wdata[7:0];
end
dfferm #(
@@ -645,7 +667,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_RDULEN_BLOCK
assign s_xpi_rdulen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_RDULEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_rdulen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_RDULEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_rdulen_d[i] = ribp.wdata[7:0];
end
dfferm #(
@@ -662,7 +685,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_DATTYP_BLOCK
assign s_xpi_dattyp_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_DATTYP && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_dattyp_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_DATTYP) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_dattyp_d[i] = ribp.wdata[1:0];
end
dfferm #(
@@ -679,7 +703,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_DATLEN_BLOCK
assign s_xpi_datlen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_DATLEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_datlen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_DATLEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_datlen_d[i] = ribp.wdata[7:0];
end
dfferm #(
@@ -696,7 +721,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_DATBIT_BLOCK
assign s_xpi_datbit_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_DATBIT && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_datbit_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_DATBIT) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_datbit_d[i] = ribp.wdata[2:0];
end
dfferm #(
@@ -713,7 +739,8 @@ module xpi_reg (
for (genvar i = 0; i < `XPI_NSS_NUM; i++) begin : XPI_HLVLEN_BLOCK
assign s_xpi_hlvlen_en[i] = s_ribp_wr_hdshk && ribp.addr[7:0] == `RIBP_XPI_HLVLEN && `XPI_LNS_NUM'(i) == s_xpi_cfgidx_q;
assign s_xpi_hlvlen_en[i] = s_ribp_wr_hdshk && (ribp.addr[7:0] == `RIBP_XPI_HLVLEN) &&
(`XPI_LNS_NUM'(i) == s_xpi_cfgidx_q);
assign s_xpi_hlvlen_d[i] = ribp.wdata[7:0];
end
dfferm #(
+3 -1
View File
@@ -11,7 +11,9 @@
".svh"
],
"format": "verible",
"lint": "strict"
"lint": "strict",
"max_line_length": 100,
"language": "systemverilog-2017-restricted"
},
"verification": {
"roots": [
+41 -3
View File
@@ -18,6 +18,21 @@ INSTANCE_RE = re.compile(
)
LEGACY_ALWAYS_RE = re.compile(r"\balways\s*@")
DECL_RE = re.compile(r"\b(?:wire|tri|wand|wor)\b")
FORBIDDEN_TOKEN_RE = {
"wildcard instance connection": re.compile(r"\.\*\s*\)"),
"defparam": re.compile(r"\bdefparam\b"),
"casex": re.compile(r"\bcasex\b"),
"full_case pragma": re.compile(r"\bfull_case\b"),
"parallel_case pragma": re.compile(r"\bparallel_case\b"),
"synthesizable delay": re.compile(r"#\s*\d"),
"task declaration": re.compile(r"\btask(?:\s+automatic)?\s+[A-Za-z_]"),
"hierarchical reference": re.compile(r"\b[A-Za-z_]\w*(?:\.[A-Za-z_]\w*){2,}\b"),
}
UNNAMED_GENERATE_RE = re.compile(
r"\bgenerate\b(?:(?!\bendgenerate\b).)*?"
r"\b(?:if|for)\b(?:(?!\bbegin\b).)*?\bbegin\s*(?!:)",
re.DOTALL,
)
LONG_LOCAL_RE = re.compile(
r"\b[sr]_[A-Za-z0-9_$]*(?:command|request|response|address|enable|error|status|"
r"counter|configuration|select|length)(?:_|$)"
@@ -96,13 +111,36 @@ def check_file(path: Path, source: str, profile: str) -> list[str]:
issues: list[str] = []
if profile == "owned":
issues.extend(instance_issues(path, source))
format_disabled = False
for number, line in enumerate(source.splitlines(), start=1):
if LEGACY_ALWAYS_RE.search(line):
code = line.split("//", 1)[0]
if "verilog_format: off" in line:
format_disabled = True
format_exception = format_disabled
if LEGACY_ALWAYS_RE.search(code):
issues.append(f"{path}:{number}: use always_ff/always_comb in owned RTL")
if re.search(r"\bwire\b", line) and not re.search(r"\binout\s+wire\b", line):
if re.search(r"\bwire\b", code) and not re.search(r"\binout\s+wire\b", code):
issues.append(f"{path}:{number}: explicit wire in owned RTL; justify net semantics")
if LONG_LOCAL_RE.search(line) and not line.lstrip().startswith("//"):
if LONG_LOCAL_RE.search(code):
issues.append(f"{path}:{number}: prefer the local short-name abbreviation")
if not format_exception:
if any(character == "\t" for character in line):
issues.append(f"{path}:{number}: tabs are not permitted in owned RTL")
if line.rstrip() != line:
issues.append(f"{path}:{number}: trailing whitespace")
if any(ord(character) > 127 for character in line):
issues.append(f"{path}:{number}: non-ASCII character")
if len(line) > 100:
issues.append(f"{path}:{number}: line exceeds 100 characters")
for description, pattern in FORBIDDEN_TOKEN_RE.items():
if pattern.search(code):
issues.append(f"{path}:{number}: {description} is not permitted")
if "verilog_format: on" in line:
format_disabled = False
if source and not source.endswith("\n"):
issues.append(f"{path}: missing final newline")
if UNNAMED_GENERATE_RE.search(source):
issues.append(f"{path}: generated if/for block must have a label")
return issues
+30
View File
@@ -58,3 +58,33 @@ def test_owned_style_allows_named_connections(tmp_path: Path) -> None:
"endmodule\n",
)
assert result.returncode == 0, result.stderr
def test_owned_style_rejects_forbidden_constructs(tmp_path: Path) -> None:
result = run_style(
tmp_path,
"module test(input logic clk_i, output logic data_o);\n"
" always_comb begin\n"
" data_o = 1'b0;\n"
" casex (data_o)\n"
" 1'bx: data_o = 1'b1;\n"
" endcase\n"
" end\n"
"endmodule\n",
)
assert result.returncode == 1
assert "casex" in result.stderr
def test_owned_style_rejects_non_ascii_and_long_lines(tmp_path: Path) -> None:
result = run_style(
tmp_path,
"module test(input logic clk_i, output logic data_o);\n"
" logic data_q;\n"
" // 非 ASCII comment\n"
" assign data_o = data_q; // " + ("x" * 101) + "\n"
"endmodule\n",
)
assert result.returncode == 1
assert "non-ASCII" in result.stderr
assert "100 characters" in result.stderr