Examples
This section provides complete examples for common workflows.
Simple Counter Project
A minimal project demonstrating basic ALY usage.
Project Structure
counter_project/
+-- .aly/
| +-- config.yaml
+-- rtl/
| +-- manifest.yaml
| +-- counter.sv
+-- tb/
| +-- manifest.yaml
| +-- tb_counter.sv
+-- constraints/
+-- arty_a7.xdc
Configuration
# .aly/config.yaml
project:
name: counter_demo
version: 1.0.0
language: systemverilog
defaults:
simulator: verilator
synthesizer: vivado
RTL Manifest
# rtl/manifest.yaml
name: counter
type: rtl
language: systemverilog
modules:
- name: counter
top: counter
files:
- counter.sv
RTL Code
// rtl/counter.sv
module counter #(
parameter WIDTH = 8
) (
input logic clk,
input logic rst_n,
input logic enable,
output logic [WIDTH-1:0] count
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n)
count <= '0;
else if (enable)
count <= count + 1'b1;
end
endmodule
Testbench
# tb/manifest.yaml
name: counter_tb
type: testbench
language: systemverilog
testbenches:
- name: tb_counter
top: tb_counter
files:
- tb_counter.sv
dependencies:
- name: counter
type: rtl
// tb/tb_counter.sv
module tb_counter;
logic clk = 0;
logic rst_n;
logic enable;
logic [7:0] count;
always #5 clk = ~clk;
counter #(.WIDTH(8)) dut (.*);
initial begin
$display("Starting counter test");
rst_n = 0;
enable = 0;
#20 rst_n = 1;
#10 enable = 1;
#100;
$display("Count = %d", count);
assert(count == 10);
$display("PASS");
$finish;
end
endmodule
Commands
# Simulate
aly sim --top tb_counter
# Lint
aly lint --module counter
# Synthesize
aly synth --module counter --part xc7a100tcsg324-1
RISC-V SoC Project
A more complex project with CPU, peripherals, and firmware.
Project Structure
riscv_soc/
+-- .aly/
| +-- config.yaml
+-- rtl/
| +-- manifest.yaml
| +-- cpu/
| | +-- cpu_core.sv
| | +-- alu.sv
| | +-- decoder.sv
| +-- peripherals/
| | +-- uart.sv
| | +-- gpio.sv
| +-- soc_top.sv
+-- tb/
| +-- manifest.yaml
| +-- tb_soc.sv
+-- fw/
| +-- manifest.yaml
| +-- boot.S
| +-- main.c
| +-- linker.ld
+-- ip/
| +-- axi_interconnect/
+-- constraints/
+-- arty_a7.xdc
Configuration
# .aly/config.yaml
project:
name: riscv_soc
version: 1.0.0
language: systemverilog
features:
firmware: true
ip: true
constraints: true
defaults:
simulator: xsim
synthesizer: vivado
simulation:
default_tool: xsim
tools:
xsim:
compile_opts: [-sv, -d SIMULATION]
synthesis:
targets:
arty_a7:
tool: vivado
part: xc7a100tcsg324-1
top: soc_top
constraints:
- constraints/arty_a7.xdc
RTL Manifest
# rtl/manifest.yaml
name: riscv_soc
type: rtl
language: systemverilog
packages:
- name: soc_pkg
file: pkg/soc_pkg.sv
scope: all
modules:
- name: alu
top: alu
files:
- cpu/alu.sv
- name: decoder
top: decoder
files:
- cpu/decoder.sv
dependencies:
- name: alu
type: rtl
- name: cpu_core
top: cpu_core
files:
- cpu/cpu_core.sv
dependencies:
- name: alu
type: rtl
- name: decoder
type: rtl
- name: uart
top: uart
files:
- peripherals/uart.sv
- name: gpio
top: gpio
files:
- peripherals/gpio.sv
- name: soc_top
top: soc_top
files:
- soc_top.sv
dependencies:
- name: cpu_core
type: rtl
- name: uart
type: rtl
- name: gpio
type: rtl
Firmware Manifest
# fw/manifest.yaml
name: soc_firmware
type: firmware
toolchain: riscv64
builds:
- name: bootloader
languages: [asm, c]
sources:
- boot.S
- main.c
linker_script: linker.ld
flags:
common: [-O2, -Wall, -nostdlib, -ffreestanding]
outputs:
- format: elf
- format: hex
Testbench
# tb/manifest.yaml
name: soc_tests
type: testbench
testbenches:
- name: tb_soc
top: tb_soc
files:
- tb_soc.sv
dependencies:
- name: soc_top
type: rtl
- name: bootloader
type: firmware
default_timeout: 10000
plusargs:
FIRMWARE: "fw/bootloader.hex"
testsuites:
- name: regression
testbenches:
- tb_soc
parallel: 1
stop_on_fail: false
Commands
# Build firmware
aly firmware bootloader
# Simulate with firmware
aly sim --top tb_soc
# Run regression
aly sim --suite regression
# Synthesize
aly synth --module soc_top --part xc7a100tcsg324-1
Multi-Target Project
A project targeting multiple FPGA boards.
# .aly/config.yaml
synthesis:
targets:
arty_a7:
tool: vivado
part: xc7a100tcsg324-1
top: fpga_top
constraints:
- constraints/arty_a7.xdc
nexys_a7:
tool: vivado
part: xc7a100tcsg324-1
top: fpga_top
constraints:
- constraints/nexys_a7.xdc
icebreaker:
tool: yosys
tech: ice40
top: fpga_top
constraints:
- constraints/icebreaker.pcf
Commands:
# Synthesize for different FPGA parts
aly synth --module fpga_top --part xc7a100tcsg324-1 # Arty/Nexys A7
aly synth --module fpga_top --tool yosys # iCE40 with Yosys
IP Reuse Example
Creating and using reusable IP.
Create IP
ip/uart/
+-- manifest.yaml
+-- rtl/
| +-- uart_tx.sv
| +-- uart_rx.sv
+-- tb/
+-- tb_uart.sv
# ip/uart/manifest.yaml
name: uart
type: ip
version: 1.0.0
vendor: internal
files:
- rtl/uart_tx.sv
- rtl/uart_rx.sv
parameters:
BAUD_RATE: 115200
DATA_BITS: 8
Use IP
# rtl/manifest.yaml
modules:
- name: soc_top
files:
- soc_top.sv
dependencies:
- name: uart
type: ip
// rtl/soc_top.sv
module soc_top (
input clk,
input rst_n,
output uart_tx,
input uart_rx
);
uart #(
.BAUD_RATE(9600)
) u_uart (
.clk(clk),
.rst_n(rst_n),
.tx(uart_tx),
.rx(uart_rx)
);
endmodule
Waveform Debugging Example
Complete workflow for debugging with waveforms.
# Run simulation with waves
aly sim --top tb_cpu --gtkwave --tool verilator
# View waveforms
gtkwave build/sim/verilator/tb_cpu/trace.vcd &
# For XSim with GUI
aly sim --top tb_cpu --gui --tool xsim
# Open waves in GTKWave automatically
aly sim --top tb_cpu --gtkwave --tool verilator
Add signals programmatically:
initial begin
$dumpfile("trace.vcd");
$dumpvars(0, tb_cpu);
end
Next Steps
Command Reference - Full command reference
Configuration - Configuration options
Architecture - Internal architecture