npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@runiq/export-verilog

v1.3.0

Published

Verilog exporter for Runiq digital circuits

Readme

@runiq/export-verilog

Verilog HDL exporter for Runiq digital circuits.

✨ Features

  • Module Generation - Convert digital profiles to Verilog modules
  • Port Declarations - Input, output, and inout ports with bus widths
  • Parameters - Module parameters with default values
  • Wire Declarations - Automatic internal wire generation
  • Instance Generation - Module instantiation with port/parameter mapping
  • Bus Support - Multi-bit signals with [N:0] notation
  • Validation - Warns about undeclared nets
  • Comprehensive Testing - 15/15 tests passing with full coverage

📦 Installation

pnpm add @runiq/export-verilog

🚀 Quick Start

import { toVerilog } from '@runiq/export-verilog';
import type { DigitalProfile } from '@runiq/core';

const counter: DigitalProfile = {
  type: 'digital',
  name: 'Counter4bit',
  modules: [
    {
      name: 'Counter4bit',
      ports: [
        { name: 'clk', dir: 'input' },
        { name: 'reset', dir: 'input' },
        { name: 'count', dir: 'output', width: 4 },
      ],
    },
  ],
  instances: [],
  nets: [{ name: 'clk' }, { name: 'reset' }, { name: 'count', width: 4 }],
};

const result = toVerilog(counter);
console.log(result.verilog);

Output:

module Counter4bit
(
  input clk,
  input reset,
  output [3:0] count
);

endmodule

📚 Examples

Simple Logic Gate

const andGate: DigitalProfile = {
  type: 'digital',
  name: 'AND2',
  modules: [
    {
      name: 'AND2',
      ports: [
        { name: 'a', dir: 'input' },
        { name: 'b', dir: 'input' },
        { name: 'y', dir: 'output' },
      ],
    },
  ],
  instances: [],
  nets: [{ name: 'a' }, { name: 'b' }, { name: 'y' }],
};

const result = toVerilog(andGate);

Output:

module AND2
(
  input a,
  input b,
  output y
);

endmodule

Parameterized Module

const register: DigitalProfile = {
  type: 'digital',
  name: 'Register',
  modules: [
    {
      name: 'Register',
      ports: [
        { name: 'clk', dir: 'input' },
        { name: 'd', dir: 'input', width: 8 },
        { name: 'q', dir: 'output', width: 8 },
      ],
      params: {
        WIDTH: 8,
        RESET_VALUE: 0,
      },
    },
  ],
  instances: [],
  nets: [{ name: 'clk' }, { name: 'd', width: 8 }, { name: 'q', width: 8 }],
};

Output:

module Register
#(
  parameter WIDTH = 8,
  parameter RESET_VALUE = 0
)
(
  input clk,
  input [7:0] d,
  output [7:0] q
);

endmodule

Hierarchical Design with Instances

const alu: DigitalProfile = {
  type: 'digital',
  name: 'ALU4bit',
  modules: [
    {
      name: 'ALU4bit',
      ports: [
        { name: 'a', dir: 'input', width: 4 },
        { name: 'b', dir: 'input', width: 4 },
        { name: 'op', dir: 'input', width: 2 },
        { name: 'result', dir: 'output', width: 4 },
      ],
    },
  ],
  instances: [
    {
      ref: 'ADDER',
      of: 'Adder4bit',
      portMap: {
        a: 'a',
        b: 'b',
        sum: 'add_result',
      },
    },
    {
      ref: 'MUX',
      of: 'Mux4to1',
      paramMap: { WIDTH: 4 },
      portMap: {
        sel: 'op',
        in0: 'add_result',
        in1: 'sub_result',
        out: 'result',
      },
    },
  ],
  nets: [
    { name: 'a', width: 4 },
    { name: 'b', width: 4 },
    { name: 'op', width: 2 },
    { name: 'result', width: 4 },
    { name: 'add_result', width: 4 },
    { name: 'sub_result', width: 4 },
  ],
};

Output:

module ALU4bit
(
  input [3:0] a,
  input [3:0] b,
  input [1:0] op,
  output [3:0] result
);

  // Internal wires
  wire [3:0] add_result;
  wire [3:0] sub_result;

  // Module instances
  Adder4bit ADDER (
    .a(a),
    .b(b),
    .sum(add_result)
  );

  Mux4to1 #(
    .WIDTH(4)
  ) MUX (
    .sel(op),
    .in0(add_result),
    .in1(sub_result),
    .out(result)
  );

endmodule

🎯 API Reference

toVerilog(profile: DigitalProfile): VerilogResult

Converts a digital profile to Verilog HDL.

Parameters:

  • profile: DigitalProfile - The digital circuit to convert

Returns:

interface VerilogResult {
  verilog: string; // Generated Verilog code
  warnings: string[]; // Any validation warnings
}

DigitalProfile

interface DigitalProfile {
  type: 'digital';
  name: string; // Top-level module name
  modules?: ModuleAst[]; // Module declarations
  instances: InstanceAst[]; // Module instances
  nets: NetAst[]; // Wire/net declarations
}

ModuleAst

interface ModuleAst {
  name: string; // Module name
  ports: PortAst[]; // Port list
  params?: Record<string, string | number>; // Parameters
}

PortAst

interface PortAst {
  name: string; // Port name
  dir: 'input' | 'output' | 'inout'; // Direction
  width?: number; // Bus width (optional)
}

InstanceAst

interface InstanceAst {
  ref: string; // Instance name
  of: string; // Module type
  paramMap?: Record<string, string | number>; // Parameter overrides
  portMap: Record<string, string>; // Port connections
}

NetAst

interface NetAst {
  name: string; // Net name
  width?: number; // Bus width (optional)
}

✅ Validation

The exporter performs validation and provides warnings for:

  • Undeclared Nets: Nets used in instances but not declared in the nets list
  • Port Conflicts: Ports that might conflict with wire declarations

Example:

const result = toVerilog(profile);

if (result.warnings.length > 0) {
  console.warn('Validation warnings:');
  result.warnings.forEach((w) => console.warn('  -', w));
}

🧪 Testing

# Run tests
pnpm test

# Watch mode
pnpm test:watch

# Coverage
pnpm test:coverage

Test Coverage:

  • ✅ Simple modules (4 tests)
  • ✅ Wire declarations (2 tests)
  • ✅ Module instances (4 tests)
  • ✅ Edge cases & validation (3 tests)
  • ✅ Complete examples (2 tests)
  • Total: 15/15 tests passing

🔧 Complete Workflow

1. Write Runiq Digital Circuit

digital "Counter" {
  module Counter {
    param WIDTH = 8
    input clk
    input reset
    output [7:0] count
  }

  net clk, reset, count[7:0]
}

2. Parse and Export

import { parse } from '@runiq/parser-dsl';
import { toVerilog } from '@runiq/export-verilog';

const content = await fs.readFile('counter.runiq', 'utf-8');
const parseResult = parse(content);

const digitalProfile = parseResult.document.profiles.find(
  (p) => p.type === 'digital'
);

const verilogResult = toVerilog(digitalProfile);

await fs.writeFile('counter.v', verilogResult.verilog);

🎨 Generated Code Style

The exporter generates clean, readable Verilog:

  • Consistent indentation - 2 spaces
  • Clear sections - Comments separate wires from instances
  • IEEE 1364 compliant - Standard Verilog-2001 syntax
  • Bus notation - [N:0] format for multi-bit signals
  • Named port connections - .port(net) style

🚀 Future Enhancements

Potential additions (not yet implemented):

  • Assign statements for continuous assignments
  • Always blocks for behavioral code
  • Initial blocks for simulation
  • Generate blocks for parameterized arrays
  • SystemVerilog features (logic, interfaces, etc.)

📖 Related Packages

  • @runiq/core - Core types and interfaces
  • @runiq/parser-dsl - Runiq DSL parser
  • @runiq/export-spice - SPICE netlist exporter (for electrical circuits)

📄 License

MIT


Status: Production ready - 15/15 tests passing ✅