Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ transcript
modelsim.ini
vsim.wlf
models/s27ks0641
syn/sky130/out/
openlane/*/runs/
openlane/*/build/
openram/
194 changes: 194 additions & 0 deletions AUDIT.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ bender update
make run #(will download proprietary models from Infineon !!)
```

## ASIC (SkyWater 130 nm)

Open-source sky130 synthesis and RTL-to-GDS hardening (Yosys + LibreLane/OpenROAD)
are provided under [`target/sky130/`](./target/sky130/README.md) — including a
synthesizable delay line and tech-cell mapping, a minimal PHY front-end and the
full controller hardened to GDS (DRC/LVS clean, ~40 MHz), plus the external pin
table and bandwidth. See also the repository audit in [`AUDIT.md`](./AUDIT.md).

## ToDos

- [ ] Support byte-aligned accesses for non-byte-size transfer
Expand Down
26 changes: 26 additions & 0 deletions openlane/hyperbus/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"DESIGN_NAME": "hyperbus_lint_wrap",

"VERILOG_FILES": ["dir::build/hyperbus_full.v"],

"CLOCK_PORT": ["clk_phy_i", "clk_sys_i"],
"//_fmax": "25 ns = 40 MHz: tightest period a pre-PnR STA sweep (worst corner",
"//_fmax2": "ss_100C) still closes at (WNS +0.29 ns @ 25 ns; negative below).",
"CLOCK_PERIOD": 25,

"FP_CORE_UTIL": 35,
"PL_TARGET_DENSITY_PCT": 45,
"RT_MAX_LAYER": "met4",

"RUN_LINTER": false,
"//_lint": "PULP RTL trips Verilator lint (empty output pins, width-expand);",
"//_lint2": "disabled so the bring-up harden proceeds. The earlier 38-vs-52-bit",
"//_lint3": "transaction-CDC truncation (an sv2v type-param mis-sizing) is now",
"//_lint4": "fixed in gen_full_rtl.sh; re-run it before re-hardening.",

"//": "Full PULP hyperbus controller (AXI4 + RegBus + dual PHY). RTL is the",
"//_2": "sv2v-lowered bender tree + sky130 delay body; regenerate with",
"//_3": "syn/sky130/gen_full_rtl.sh. Two clocks (sys + phy) plus PHY-generated",
"//_4": "divided/90-deg clocks that are unconstrained here -> bring-up harden,",
"//_5": "not signoff (see AUDIT.md CDC/generated-clock notes)."
}
24 changes: 24 additions & 0 deletions openlane/hyperbus_phy_sky130/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"DESIGN_NAME": "hyperbus_phy_sky130",

"VERILOG_FILES": [
"dir::../../target/sky130/tech_cells_sky130.sv",
"dir::../../target/sky130/configurable_delay.sky130.sv",
"dir::../../src/hyperbus_clk_gen.sv",
"dir::../../src/hyperbus_ddr_out.sv",
"dir::../../src/hyperbus_clock_diff_out.sv",
"dir::../../src/hyperbus_delay.sv",
"dir::../../target/sky130/hyperbus_phy_sky130.sv"
],
"VERILOG_DEFINES": ["SKY130_NATIVE_CELLS"],

"CLOCK_PORT": "clk_phy_i",
"CLOCK_PERIOD": 40,

"FP_SIZING": "absolute",
"DIE_AREA": "0 0 90 90",
"FP_CORE_UTIL": 35,
"PL_TARGET_DENSITY_PCT": 45,

"RT_MAX_LAYER": "met4"
}
18 changes: 18 additions & 0 deletions openlane/hyperbus_small/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"DESIGN_NAME": "hyperbus_lint_wrap",

"VERILOG_FILES": ["dir::../hyperbus/build/hyperbus_full_small.v"],

"CLOCK_PORT": ["clk_phy_i", "clk_sys_i"],
"CLOCK_PERIOD": 25,

"FP_CORE_UTIL": 35,
"PL_TARGET_DENSITY_PCT": 45,
"RT_MAX_LAYER": "met4",

"RUN_LINTER": false,

"//": "Small variant: AxiDataWidth=32, NumPhys=1 (vs the 128b/dual-PHY main",
"//_2": "build). Same 25 ns target for an apples-to-apples area comparison.",
"//_3": "Regenerate RTL with: AXIW=32 NPHYS=1 OUT_NAME=hyperbus_full_small.v zsh syn/sky130/gen_full_rtl.sh"
}
4 changes: 2 additions & 2 deletions src/hyperbus_synth_wrap.sv
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module hyperbus_lint_wrap #(
// HyperBus parameters
parameter int unsigned NumChips = 2,
parameter int unsigned NumPhys = 2,
parameter int unsigned IsClockODelayed = 0,
parameter bit UsePhyClkDivider = 1,
// AXI parameters
parameter int unsigned AxiIdWidth = 6,
parameter int unsigned AxiAddrWidth = 48,
Expand Down Expand Up @@ -133,7 +133,7 @@ module hyperbus_lint_wrap #(
hyperbus #(
.NumChips ( NumChips ),
.NumPhys ( NumPhys ),
.IsClockODelayed ( IsClockODelayed ),
.UsePhyClkDivider ( UsePhyClkDivider ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiIdWidth ( AxiIdWidth ),
Expand Down
11 changes: 7 additions & 4 deletions src/hyperbus_w2phy.sv
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,19 @@ module hyperbus_w2phy #(
data_buffer_d.strb = data_i.strb;
data_buffer_d.last = data_i.last;
if(first_tx_q) begin
for (int i=0; i<byte_idx_q; i++)
data_buffer_d.strb[i]='0;
// Constant loop bound + runtime guard: portable to synthesis
// tools (e.g. Yosys) that require static for-loop bounds.
for (int i=0; i<NumAxiBytes; i++)
if (i < byte_idx_q) data_buffer_d.strb[i]='0;
end
end else begin
data_buffer_d.strb[byte_idx_q +: (2*NumPhys)] = data_i.strb[byte_idx_q +: (2*NumPhys)];
data_buffer_d.data[byte_idx_q*8 +: (8*NumPhys)] = data_i.data[byte_idx_q*8 +: (8*NumPhys)];
data_buffer_d.last = data_i.last;
if(first_tx_q) begin
for (int j=0; j<byte_idx_q; j++)
data_buffer_d.strb[j]='0;
// Constant loop bound + runtime guard (see note above).
for (int j=0; j<NumAxiBytes; j++)
if (j < byte_idx_q) data_buffer_d.strb[j]='0;
end
end
end
Expand Down
96 changes: 96 additions & 0 deletions syn/sky130/gen_full_rtl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env zsh
# Copyright 2026. SPDX-License-Identifier: SHL-0.51
#
# Generate a single flat Verilog-2005 file for the FULL PULP hyperbus
# controller (AXI4 + RegBus + PHY) for open-source ASIC synthesis.
#
# Pipeline: bender (resolve deps + file list) -> sv2v (SV -> Verilog)
# Output: openlane/hyperbus/build/$OUT_NAME (top: hyperbus_lint_wrap)
#
# Config knobs (env vars; defaults = the documented 128b / dual-PHY build):
# AXIW=128 AxiDataWidth
# NPHYS=2 NumPhys (1 or 2)
# OUT_NAME=hyperbus_full.v output filename under the build dir
# e.g. small variant: AXIW=32 NPHYS=1 OUT_NAME=hyperbus_full_small.v zsh gen_full_rtl.sh
#
# Requirements on PATH: bender, sv2v. Run from the repo root.
#
# Notes / gotchas baked in here (learned the hard way):
# * zsh does NOT word-split unquoted $var -> use ${(f)VAR} to split on lines.
# * sv2v resolves `include search dirs only via RELATIVE -I paths here, so we
# strip the repo-root prefix from bender's absolute include dirs.
# * -DVERILATOR -DXSIM strip the sim-only SVA (`default disable iff`, etc.)
# that sv2v 0.0.13 cannot parse; -DSYNTHESIS drops other sim-only blocks.
# * -DSKY130_NATIVE_CELLS selects the hard sky130 delay/ICG cells.
# * The bender source list has no `configurable_delay` body (behav/fpga are
# target-gated out), so we append target/sky130/configurable_delay.sky130.sv.
# * sv2v --top bakes the wrapper's DEFAULT params, so to vary AxiDataWidth/
# NumPhys we feed sv2v a build-local copy of the wrapper with the defaults
# patched (src/ stays pristine).
set -e

AXIW=${AXIW:-128}
NPHYS=${NPHYS:-2}
OUT_NAME=${OUT_NAME:-hyperbus_full.v}

ROOT="${0:A:h}/../.."
cd "$ROOT"
OUT=openlane/hyperbus/build
mkdir -p "$OUT"

command -v bender >/dev/null || { echo "ERROR: bender not on PATH" >&2; exit 1; }
command -v sv2v >/dev/null || { echo "ERROR: sv2v not on PATH" >&2; exit 1; }

# Build-local wrapper with AxiDataWidth / NumPhys defaults patched for this run.
WRAP="$OUT/wrap_gen.sv"
sed -E "s/(AxiDataWidth *= *)128/\1${AXIW}/; s/(NumPhys +)= 2/\1= ${NPHYS}/" \
src/hyperbus_synth_wrap.sv > "$WRAP"

# Resolve dependencies from the committed Bender.lock (no re-resolve).
bender script verilator > "$OUT/bender.vlt.f"

INCS="$(grep '+incdir+' "$OUT/bender.vlt.f" | sed "s/+incdir+//; s#$PWD/##; s/^/-I/" | sort -u)"
FILES="$(grep -E '\.sv$|\.v$' "$OUT/bender.vlt.f" | sed "s#$PWD/##")"

# --top elaborates from hyperbus_lint_wrap and emits ONLY reachable modules
# (prunes unused apb/reg/axi modules that carry SV constructs yosys can't
# parse, and binds concrete parameters).
FV="$OUT/$OUT_NAME"
sv2v --top=hyperbus_lint_wrap \
-DSYNTHESIS -DVERILATOR -DXSIM -DSKY130_NATIVE_CELLS \
${(f)INCS} ${(f)FILES} \
target/sky130/configurable_delay.sky130.sv \
"$WRAP" \
> "$FV"

# --- Post-process: pin the "-1 must-override" parameter defaults --------------
# The hyperbus RTL uses `parameter X = -1` as a "must override" idiom (flagged
# in AUDIT.md). sv2v's --top specialization decomposes AXI *type* parameters and
# in doing so leaves some scalar defaults unbound, so they resolve to -1
# (0xFFFFFFFF) and blow up part-select widths in Yosys. This design is used in
# exactly ONE configuration per generation, so we pin the defaults to those
# concrete values. A real instantiation still overrides them; only the
# otherwise-garbage unbound cases change.
#
# Also: sv2v mis-sizes the HyperBurstWidth width-param it extracts from
# `parameter type T` as [0:0] (1 bit), truncating 15->1 and shrinking the
# transaction CDC data ports from 52 to 38 bits (dropping the write flag +
# burst MSBs). Widen it back to 32 bits.
sed -i '' \
-e 's/parameter \[0:0\] \([A-Za-z0-9_]*HyperBurstWidth\)/parameter [31:0] \1/g' \
"$FV"
sed -i '' \
-e "s/\(parameter \[31:0\] AxiDataWidth\) = -1;/\1 = ${AXIW};/" \
-e 's/\(parameter \[31:0\] AxiAddrWidth\) = -1;/\1 = 48;/' \
-e 's/\(parameter \[31:0\] AxiIdWidth\) = -1;/\1 = 6;/' \
-e 's/\(parameter \[31:0\] AxiUserWidth\) = -1;/\1 = 1;/' \
-e 's/\(parameter \[31:0\] NumChips\) = -1;/\1 = 2;/' \
-e "s/\(parameter \[31:0\] NumPhys\) = -1;/\1 = ${NPHYS};/" \
-e 's/\(parameter \[31:0\] RegAddrWidth\) = -1;/\1 = 32;/' \
-e 's/\(parameter \[31:0\] RegDataWidth\) = -1;/\1 = 32;/' \
-e 's/\(parameter \[31:0\] BurstLength\) = -1;/\1 = 15;/' \
-e 's/\(parameter \[RegDataWidth - 1:0\] RstChipBase\) = -1;/\1 = 0;/' \
-e "s/\(parameter \[RegDataWidth - 1:0\] RstChipSpace\) = -1;/\1 = 'h10000;/" \
"$FV"

echo "Wrote $FV (AxiDataWidth=${AXIW}, NumPhys=${NPHYS}, $(grep -c '^module ' "$FV") modules)"
24 changes: 24 additions & 0 deletions syn/sky130/inspect.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# OpenROAD script: load the yosys sky130 netlist, do a minimal
# floorplan + placement, and open the GUI to inspect the core.
# openroad -gui syn/sky130/inspect.tcl
# (A gate-level netlist has no physical data; we place it so there is
# something to view. Adjust die/core size or density as needed.)

set pdk [lindex [glob $env(HOME)/.volare/volare/sky130/versions/*/sky130A/libs.ref/sky130_fd_sc_hd] 0]

read_lef $pdk/techlef/sky130_fd_sc_hd__nom.tlef
read_lef $pdk/lef/sky130_fd_sc_hd.lef
read_liberty $pdk/lib/sky130_fd_sc_hd__tt_025C_1v80.lib

read_verilog [file dirname [info script]]/out/hyperbus_phy_sky130.netlist.v
link_design hyperbus_phy_sky130

# ~60x60 um die, 50x50 um core (~50% utilisation for ~1250 um2 of cells)
initialize_floorplan -die_area {0 0 60 60} -core_area {5 5 55 55} -site unithd
make_tracks

place_pins -hor_layers met3 -ver_layers met2
global_placement -density 0.60
detailed_placement

# In -gui mode OpenROAD drops into the GUI here. Headless? add: exit
45 changes: 45 additions & 0 deletions syn/sky130/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# Copyright 2026. SPDX-License-Identifier: SHL-0.51
#
# Minimal sky130 ASIC synthesis of the HyperBus PHY front-end using Yosys.
# Produces a gate-level netlist mapped to sky130_fd_sc_hd standard cells plus
# an area / cell-count report. This is a synthesis (STA-less) bring-up flow,
# not full P&R -- see target/sky130/README.md.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
OUT="${ROOT}/syn/sky130/out"
mkdir -p "${OUT}"

# Locate the sky130_fd_sc_hd typical-corner Liberty (installed via volare).
: "${SKY130_LIB:=$(ls "${HOME}"/.volare/volare/sky130/versions/*/sky130A/libs.ref/sky130_fd_sc_hd/lib/sky130_fd_sc_hd__tt_025C_1v80.lib 2>/dev/null | head -1)}"
if [[ -z "${SKY130_LIB}" || ! -f "${SKY130_LIB}" ]]; then
echo "ERROR: sky130_fd_sc_hd tt_025C_1v80 Liberty not found. Set SKY130_LIB." >&2
exit 1
fi
echo "Using Liberty: ${SKY130_LIB}"

TOP=hyperbus_phy_sky130

yosys -q -p "
read_liberty -lib ${SKY130_LIB}
read_verilog -sv -DSKY130_NATIVE_CELLS ${ROOT}/target/sky130/tech_cells_sky130.sv
read_verilog -sv -DSKY130_NATIVE_CELLS ${ROOT}/target/sky130/configurable_delay.sky130.sv
read_verilog -sv ${ROOT}/src/hyperbus_clk_gen.sv \
${ROOT}/src/hyperbus_ddr_out.sv \
${ROOT}/src/hyperbus_clock_diff_out.sv \
${ROOT}/src/hyperbus_delay.sv \
${ROOT}/target/sky130/hyperbus_phy_sky130.sv
hierarchy -check -top ${TOP}
synth -top ${TOP} -flatten
dfflibmap -liberty ${SKY130_LIB}
abc -liberty ${SKY130_LIB}
setundef -zero
clean -purge
write_verilog -noattr ${OUT}/${TOP}.netlist.v
tee -o ${OUT}/${TOP}.area.rpt stat -liberty ${SKY130_LIB}
"

echo
echo "Netlist : ${OUT}/${TOP}.netlist.v"
echo "Area : ${OUT}/${TOP}.area.rpt"
Loading