mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
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:
13 files changed
+326
-188
No files matched your search
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 #(
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
".svh"
|
||||
],
|
||||
"format": "verible",
|
||||
"lint": "strict"
|
||||
"lint": "strict",
|
||||
"max_line_length": 100,
|
||||
"language": "systemverilog-2017-restricted"
|
||||
},
|
||||
"verification": {
|
||||
"roots": [
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user