Install
$ agentstack add skill-phamcuong21478-rtl-skills-vdesign ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Verilog Designer
Overview
This guide defines the workflow for generating a design proposal, documentation, and a skeleton RTL module from a Markdown requirement file.
The input is a .md requirement file that describes what the module should do, typically ./ddoc/_req.md produced by varch. The output is:
- A proposal file with function description, architecture and algorithm if applicable
- A design documentation file
- A backbone Verilog file with
//@direction comments, ready for implementation byvfill
vdesign runs once per new submodule. Reused lib modules have no _req.md (they are already designed and documented), so there is nothing here to drive — vdesign simply skips them; varch still instantiates them in the skeleton.
Module Name Derivation
All output file names are derived from the module name, not the raw requirement file name. The module name is the requirement file base name with any trailing _req removed.
Example:
- requirement
./ddoc/foo_ctrl_req.md→ module namefoo_ctrl
Use this module name consistently for the proposal, documentation, and RTL backbone file names below.
Preconditions
Two stop conditions, checked before anything is written:
- Requirement file missing.
./ddoc/_req.mddoes not exist → stop and
report: run varch first (or place a hand-written requirement file). Never design from a module name alone.
- Target is the IP top. The module name resolves to
_top→ refuse. The
top-level integration skeleton is owned by varch (it has no _req.md, and its //@ are integration notes, not fill directions); vdesign generates submodule backbones only.
Before You Start — Re-run Safety
vdesign overwrites three artifacts. Two of them carry hand-owned downstream content once the flow has progressed past vfill:
rtl/.v— aftervfill, this holds the real implementation and every//@marker has been converted away. A blind re-generate destroys the implementation.ddoc/_proposal.md—vfillrecords design updates and debug notes in its## Implementation Notes (vfill)section (seeded empty in Step 2). A blind re-generate clobbers them.
So before writing anything, classify the current state of the backbone:
| State | How to detect | Action | |-------|---------------|--------| | Fresh | rtl/.v does not exist | Generate all three outputs normally. | | Backbone only | rtl/.v exists and still contains //@ markers, no real logic | Safe to regenerate — the requirement changed and nothing downstream depends on it yet. | | Filled | rtl/.v has no //@ markers (the same marker vflow uses to detect completion, CodingStyle §18) / contains implemented logic, or the proposal's ## Implementation Notes (vfill) section has content | Stop and confirm with the user before overwriting. Re-running discards vfill's implementation and notes. The safe path is to re-run vdesign before vfill; after that, requirement changes must be reconciled into the filled RTL by hand. |
This mirrors how varch guards _top.v against clobbering integration edits.
Step 1 - Read Requirements and Generate Proposal
Read the target requirement .md file and extract the design intent.
A varch-generated _req.md has two parts separated by the marker line ``:
- Structural section (above the marker) — overview, parameters, and the port/interface table. This is the authoritative interface contract:
varchalready fixed these port and parameter names, widths, defaults, and directions and wired_top.vto them by name. Carry them through verbatim — do not rename, re-width, re-default, or re-derive a port or parameter. Renaming a port or parameter here breaks the skeleton wiring three phases later. - Hand-owned functional section (below the marker) —
## Functional Description. This is the real design intent the proposal and documentation must stay faithful to.
(If the requirement has no marker line — e.g. it was hand-written — treat the whole file as intent and take ports from whatever port table it provides.)
If the design genuinely needs a port or parameter the requirement does not list, that is an architecture change, not a local fix. Do not invent it here — adding a port that _top.v does not wire breaks integration. Stop and flag the gap to the user so it can be resolved in varch (which updates the architecture document, the _req.md, and the skeleton together), then re-run vdesign against the corrected requirement.
Based on the requirements, generate a design proposal. The proposal must include:
- Functional description of the module, consistent with the requirement's functional section
- Port list with signal names, directions, and widths — taken verbatim from the requirement's structural port table
- Parameter list with names, defaults, and legal ranges — names and defaults taken verbatim from the requirement's structural parameter table (including
RS_LVfor a clocked module); the legal range is a design decision made here (it feeds the doc's Parameters table,ModuleDocContract §2, and ultimately the release datasheet) - Algorithm description, if applicable
- Micro-architecture design — the heart of the proposal; which artifacts are mandatory depends on what the module contains (see "Micro-architecture design" below)
- Intended timing — mandatory for every clocked module: latency from input to output, pipeline depth, and throughput. If there is no fixed latency, state that explicitly (e.g. "handshake-bound, no fixed latency") rather than omitting the section —
vassert's Latency/Throughput properties and the doc's mandatory Timing Characteristics section (ModuleDocContract §6) are both derived from this. A purely combinational module states "combinational".
Pattern scan (do this before finalizing the architecture)
Run an explicit two-part scan against .claude/skills/shared/DesignPatterns.md — recognition is the weak link, so make it a deliberate pass, not incidental noticing:
- Feature scan. For each pattern, read its Recognize when line against the
requirement's functional section. These are phrased in requirement/symptom language (back-pressure, arbitration, occupancy, configuration registers, …) so the match is keyword-level. A requirement may hit several.
- Reflex scan. Walk the Reflex triggers table against the architecture you
are about to choose. These patterns (P4, P8, P9, P10, P6, P7, P12) fire from a structural commitment you make — a RAM, a pipeline, a bus, an array port — not from anything the requirement says, so they are the ones silently missed. The moment you decide to put state in a RAM, the preclear (P4) and read-during-write (P8) checks become mandatory.
For every hit, shape the architecture after the matching pattern and name the pattern in the proposal's architecture section (e.g. "the per-id count RAM needs P4 preclear + P8 forwarding"; "buffer the output with vb_stream_fifo, P1"). This keeps related modules consistent and tells vfill which idiom to implement. Be precise — match a pattern only when its discriminator actually holds (don't add a buffer where always-ready upstream is fine). Do not paste the pattern's code into the proposal — reference it by name; the actual widths and reset scope are derived per module.
Using library modules inside the design
A pattern hit (or the architecture itself) often calls for a standard building block — a stream FIFO, a synchronizer, a dual-port RAM. Before designing one from scratch, check ./lib for a module that already provides it (the same reuse-first rule varch applies at the IP level):
- Take its ports and parameters verbatim from its
.mddocumentation
(the doc follows ModuleDocContract and is usable without reading the RTL; fall back to the source only if the doc lacks them). Never invent, rename, or re-width a library port; bind only the parameters it actually declares.
- Record the reuse in the proposal's architecture section (library path +
instance role), so vfill and the debuggers know the block is library code and do not re-derive or re-implement it.
- The instantiation goes into the backbone as structural code (Step 3), not
into a //@ marker — wiring a known, fixed interface is a design decision made here; leaving it to vfill forces a re-derivation of the same interface.
Micro-architecture design (the heart of the proposal)
The proposal is a design, not a restatement of the requirement: every decision vfill would otherwise have to make while implementing is made here, where it can be reviewed. Which artifacts are mandatory depends on what the module contains — detect, then design:
| The module has… | Then the proposal must carry | |---|---| | more than one internal block or stage | Datapath & control diagram (mermaid): the internal blocks, the signals between them named per CodingStyle §3 (s0_/s1_ stage prefixes, _ff registers), and which part is control vs datapath | | control sequencing (modes, multi-step transactions, protocol handling) | FSM design: the state list with a one-line meaning each; the encoding choice (localparam binary / one-hot — and why); the reset state; a transition table or mermaid stateDiagram-v2 covering every documented stimulus, including the error/abort paths; Moore vs Mealy per output; recovery from an illegal state (the mandatory default:) | | latency > 1 cycle | Pipeline table — one row per stage: stage name (s0/s1/…), the registers it owns (named), the computation it performs, its valid qualifier, and its behavior on stall/bubble. The rows must sum to the ## Timing latency. State the back-pressure strategy (full-pipe stall vs skid/elastic buffer) and the pattern it follows | | internal state | Storage inventory: every register, counter, and RAM with its width, reset value (or "no reset, qualified by valid" per CodingStyle §5/§14), and the reflex-pattern rulings that apply (P4 preclear, P8 read-during-write, …) | | a non-obvious choice (algorithm variant, encoding, RAM vs FF array, single- vs multi-cycle) | Decision note: one or two sentences — the choice, the alternative rejected, and why |
All diagrams (architecture, FSM state, algorithm flow) are written in mermaid format.
A module with none of the above — pure combinational glue, a trivial register slice — may compress the architecture section to a paragraph. Omission is allowed only when there is genuinely nothing to decide, never because the design is merely unwritten.
The backbone mirrors the micro-architecture (Step 3). Each diagram block / pipeline stage becomes a section banner; the //@ markers name the proposal's states and stages (e.g. //@ implement the IDLE→LOAD→RUN→DRAIN FSM from the proposal, one-hot, default: recover to IDLE), so vfill implements the designed FSM and pipeline rather than inventing its own.
Step 2 - Generate Proposal and Documentation Files
Generate the following files:
Proposal File
Create a new Markdown file in the ./ddoc folder, alongside the requirement file.
Output file rules:
- Use the module name as the base name
- Append
_proposalbefore the extension - Use the
.mdextension
Example:
- requirement
foo_req.md→./ddoc/foo_proposal.md
Proposal sections
The proposal carries these sections in order (omitting only the ones Step 1 marks optional): ## Function Description, ## Ports, ## Parameters (with legal ranges), ## Architecture (the micro-architecture artifacts from Step 1 — datapath/control diagram, FSM design, pipeline table, storage inventory, decision notes — naming any matched patterns and reused lib modules), ## Algorithm, ## Timing, and — always last — an empty seed:
## Implementation Notes (vfill)
The seed is the contract that keeps re-runs safe: vfill writes its notes inside this section only, updating in place rather than appending duplicates, so "has vfill touched this proposal?" reduces to one check — whether the section has content (the Re-run Safety table above relies on it).
Design Documentation File
Create a new Markdown file in the ./doc folder.
Output file rules:
- Use the module name as the base name
- Use the
.mdextension
Example:
- requirement
foo_req.md→./doc/foo.md
Required Content for the Design Documentation
The design documentation must follow the module documentation contract defined in .claude/skills/shared/ModuleDocContract.md. Populate every required section of that contract from the proposal and the requirement file.
The functional description must be consistent with the proposal and with the requirement's hand-owned functional section. Because the RTL is not yet implemented at this stage, derive the port table, reset values, and timing characteristics from the proposal's port list and architecture; if a value is not yet decided, state the intended value from the proposal rather than leaving it blank. The reset section must reflect the project convention: synchronous reset, rst_n compared against RS_LV (default active-low).
For a register-bearing module, the Register Map (ModuleDocContract §9) is designed here: addresses, access types (RO/RW/W1C/RC), and reset values come from the requirement's register list plus the architecture's decode design — they are design decisions, not implementation details, so they must not be deferred to vfill. The Instantiation Template (§11) binds every parameter to the default from the structural parameter table.
Step 3 - Create Backbone RTL Module
Create a skeleton Verilog file in the ./rtl folder.
Output file rules:
- Use the module name as the base name
- Use the
.vextension
Example:
- requirement
foo_req.md→./rtl/foo.v
This skill generates backbones for submodules only. The top-level integration skeleton ./rtl/_top.v is owned by varch; do not create or overwrite it here.
Backbone Structure
The backbone must be style-compliant from the start — vfill fills it in place, so the scaffold must already match .claude/skills/shared/CodingStyle.md, not just the empty-logic shape. When the proposal names a design pattern (Step 1), lay the section dividers and //@ markers out after that pattern's canonical shape in .claude/skills/shared/DesignPatterns.md, keeping the markers plain-English (no code, CodingStyle §18). It must include:
- Plain Verilog-2005 only (
CodingStyle §0) — the backbone is the future
synthesizable RTL; no SystemVerilog constructs.
- `
defaultnettype none `at the top anddefaultnettype wire `at the end (CodingStyle §14`). - Module declaration with all ports from the proposal, ANSI style, with
//!Doxygen doc-comments on every port and parameter (CodingStyle §1,§10). RS_LVas the last parameter of the (clocked) module, default0(CodingStyle §1,§12).//@direction comments that guidevfillon what to implement in each section.- Section dividers using the standard banner format, indented to body level (4 spaces) (
CodingStyle §4). - Empty logic bodies — no implementation. The one exception is **structural code
for a reused library module** (Step 1): instantiate it here with named port connections (CodingStyle §9), its interface taken verbatim from the lib doc; any glue logic around it stays a //@ direction for vfill.
Port and signal naming follows CodingStyle §3 (do not re-derive a partial copy of those rules here): s_/m_ interface prefixes, _ff for flip-flops, s0_/s1_ pipeline-stage prefixes, etc. Port names themselves come straight from the requirement's structural port table (see Step 1).
Example backbone structure:
`default_nettype none
module foo #(
parameter DATA_W = 8, //! data bus
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [phamcuong21478](https://github.com/phamcuong21478)
- **Source:** [phamcuong21478/rtl-skills](https://github.com/phamcuong21478/rtl-skills)
- **License:** Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.