Skip to main content

An intuitive Python based HDL code generator for Verilog/SystemVerilog and VHDL.

Project description

HDLGen

Python PyPI

Ruff Tests License: Apache 2.0

A Python library for programmatically generating HDL (Hardware Description Language) code including Verilog, SystemVerilog, and VHDL.

Features

  • Intuitive context manager-based API
  • Support for multiple HDL languages
  • Clean, readable HDL output generation
  • Python-native approach to hardware description

Installation

pip install hdlgen

Quick Start

from rtlgen import CodeGen

# Create a Verilog generator
gen = CodeGen("conditional_module.v", "verilog")

# Create a module with ports and logic
with gen.Module("conditional_module") as m:
    # Define internal logic
    with m.LogicRegion() as lr:
        # Create signals
        clk = lr.Signal("clk")
        reset = lr.Signal("reset")
        counter = lr.Signal("counter", 8)
        
        # Create an always block for synchronous logic
        with lr.BeginEnd("always @(posedge clk)"):
            with lr.IfElse("reset"):
                lr.Assign(counter, 0, blocking=True)
            with lr.Else():
                lr.Assign(counter, counter + 1, blocking=True)

# file auto written when gen.Module out of context

Side-by-Side Examples

Here are examples showing HDLGen Python code and the resulting HDL output for Verilog, SystemVerilog, and VHDL.

Module and Signal Declaration

Verilog

Python Code (Verilog)Generated Verilog
from rtlgen import CodeGen

gen = CodeGen("module.v", "verilog")

with gen.Module("test_module") as m:
    with m.LogicRegion() as lr:
        signal = lr.Signal("test_signal", 8)
        single_bit = lr.Signal("single_bit")
module test_module (
);

    // Logic
    reg [7:0] test_signal;
    reg single_bit;

endmodule

SystemVerilog

Python Code (SystemVerilog)Generated SystemVerilog
from rtlgen import CodeGen

gen = CodeGen("module.sv", "systemverilog") # Target SystemVerilog

with gen.Module("test_module") as m:
    with m.LogicRegion() as lr:
        # SystemVerilog typically uses 'logic' type
        test_signal = lr.Signal("test_signal", 8, type="logic")
        single_bit = lr.Signal("single_bit", type="logic")
module test_module (
);

    // Logic
    logic [7:0] test_signal; // 'logic' type
    logic single_bit;       // 'logic' type

endmodule

VHDL

Python Code (VHDL)Generated VHDL
from rtlgen import CodeGen

gen = CodeGen("module.vhd", "vhdl") # Target VHDL
gen.Library("ieee")
gen.Use("ieee.std_logic_1164.all")

with gen.Module("test_module") as m:
    # In VHDL, signals are part of an architecture
    with m.Architecture("rtl") as arch:
        test_signal = arch.Signal("test_signal", "std_logic_vector(7 downto 0)")
        single_bit = arch.Signal("single_bit", "std_logic")
library ieee;
use ieee.std_logic_1164.all;

entity test_module is
    -- Ports would be defined here if any
end entity test_module;

architecture rtl of test_module is
    -- Signals
    signal test_signal : std_logic_vector(7 downto 0);
    signal single_bit  : std_logic;
begin
    -- Concurrent statements or processes
end architecture rtl;

If-Else Conditions

Verilog

Python Code (Verilog)Generated Verilog
from rtlgen import CodeGen

gen = CodeGen("conditional_module.v", "verilog")

with gen.Module("conditional_module") as m:
    with m.LogicRegion() as lr:
        clk = lr.Signal("clk")
        reset = lr.Signal("reset")
        counter = lr.Signal("counter", 8)
        
        with lr.BeginEnd("always @(posedge clk)"): # Synchronous block
            with lr.IfElse("reset"):
                lr.Assign(counter, 0, blocking=False) # Non-blocking
            with lr.Else():
                lr.Assign(counter, counter + 1, blocking=False) # Non-blocking
module conditional_module (
);

    // Logic
    reg clk;
    reg reset;
    reg [7:0] counter;
    
    always @(posedge clk) begin
        if (reset) begin
            counter <= 0; // Non-blocking assignment
        end else begin
            counter <= counter + 1; // Non-blocking assignment
        end
    end

endmodule

SystemVerilog

Python Code (SystemVerilog)Generated SystemVerilog
from rtlgen import CodeGen

gen = CodeGen("conditional_module.sv", "systemverilog")

with gen.Module("conditional_module") as m:
    with m.LogicRegion() as lr:
        clk = lr.Signal("clk", type="logic")
        reset = lr.Signal("reset", type="logic")
        counter = lr.Signal("counter", 8, type="logic")

        # Using always_ff for synchronous logic
        with lr.AlwaysFF("@(posedge clk or posedge reset)") as ff_block: # Async reset
            with ff_block.If("reset"): # Active-high reset
                ff_block.Assign(counter, "\'0\'", blocking=False) # SV literal assignment
            with ff_block.Else():
                ff_block.Assign(counter, counter + 1, blocking=False)
module conditional_module (
);

    // Logic
    logic clk;
    logic reset;
    logic [7:0] counter;
    
    always_ff @(posedge clk or posedge reset) begin // Assuming asynchronous reset
        if (reset) begin
            counter <= \'0\';
        end else begin
            counter <= counter + 1;
        end
    end

endmodule

VHDL

Python Code (VHDL)Generated VHDL
from rtlgen import CodeGen

gen = CodeGen("conditional_module.vhd", "vhdl")
gen.Library("ieee")
gen.Use("ieee.std_logic_1164.all")
gen.Use("ieee.numeric_std.all") # For arithmetic

with gen.Module("conditional_module") as m:
    # Define Entity Ports
    clk = m.Port("clk_i", "in", "std_logic")
    reset = m.Port("reset_i", "in", "std_logic")
    counter_out = m.Port("counter_o", "out", "std_logic_vector(7 downto 0)")

    with m.Architecture("rtl") as arch:
        # Internal signal for counter logic, using 'unsigned' for arithmetic
        counter_reg = arch.Signal("counter_s", "unsigned(7 downto 0)")

        with arch.Process([clk, reset]) as p: # Process sensitive to clk and reset
            with p.If(f"{reset} = \'1\'"): # Asynchronous reset
                p.Assign(counter_reg, "(others => \'0\')")
            with p.ElsIf(f"rising_edge({clk})"):
                p.Assign(counter_reg, f"{counter_reg} + 1")
        
        # Assign internal signal to output port
        arch.Assign(counter_out, f"std_logic_vector({counter_reg})")
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity conditional_module is
    port (
        clk_i     : in  std_logic;
        reset_i   : in  std_logic;
        counter_o : out std_logic_vector(7 downto 0)
    );
end entity conditional_module;

architecture rtl of conditional_module is
    signal counter_s : unsigned(7 downto 0);
begin
    process (clk_i, reset_i)
    begin
        if reset_i = \'1\' then
            counter_s <= (others => \'0\');
        elsif rising_edge(clk_i) then
            counter_s <= counter_s + 1;
        end if;
    end process;

    counter_o <= std_logic_vector(counter_s);
end architecture rtl;

Supported HDL Languages

  • Verilog
  • SystemVerilog
  • VHDL

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hdlgen-0.0.1.dev1.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hdlgen-0.0.1.dev1-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file hdlgen-0.0.1.dev1.tar.gz.

File metadata

  • Download URL: hdlgen-0.0.1.dev1.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.7

File hashes

Hashes for hdlgen-0.0.1.dev1.tar.gz
Algorithm Hash digest
SHA256 c8d6cf3a4f24c88945b0e1b5edc0498d3eaa27790dd61a69296379ac342f230c
MD5 3147ee7cc44e94a4c2d8a9fff8ae10a4
BLAKE2b-256 a9f3d1ed3155bda687556b66a9d83867a263b2572958f4ca512c282213690442

See more details on using hashes here.

File details

Details for the file hdlgen-0.0.1.dev1-py3-none-any.whl.

File metadata

File hashes

Hashes for hdlgen-0.0.1.dev1-py3-none-any.whl
Algorithm Hash digest
SHA256 a10a39e47cb9f13ee5821c4112a7de7bef79b32cff65a9c69fcfcca9afe5d2cd
MD5 4faf838d9693554fab7a61c4c5bab3e7
BLAKE2b-256 bc85a86b9e479fcae360b9357172fd2e64a63eec2931a6238290024a1a80ead9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page