欢迎来到芯片音乐的世界!本课程将带你从零开始,用Verilog硬件描述语言制作属于你自己的芯片音乐。我们将从最基础的波形发生器开始,逐步构建出完整的音乐合成系统。
芯片音乐(Chiptune),又称8位音乐(8-bit Music),是一种利用声音芯片(Sound Chip)或可编程声音发生器(PSG)生成的电子音乐。它的黄金时代是20世纪80年代,当时的游戏机如NES(FC)、Game Boy、Commodore 64等都使用专用声音芯片来产生游戏音效和背景音乐。
| 芯片 | 主机 | 通道数 | 波形类型 | 特色 |
|---|---|---|---|---|
| 2A03 (RP2A03) | NES/FC | 5 | 2方波+1三角+1噪声+1DPCM | 方波占空比可调 |
| SN76489 | Sega Master System | 4 | 3方波+1噪声 | 衰减器控制音量 |
| AY-3-8910 | MSX/ZX Spectrum | 3 | 方波+噪声 | 硬件包络发生器 |
| SID 6581 | C64 | 3 | 锯齿/三角/脉冲/噪声 | 环形调制+滤波器 |
| DMG-CPU | Game Boy | 4 | 2方波+1波表+1噪声 | 波表通道可自定义波形 |
芯片音乐的核心限制在于有限的硬件资源。这些限制反而催生了独特的创作风格:
Verilog是硬件描述语言(HDL),用它来实现芯片音乐有独特的优势:
本课程分为5个阶段,共25课:
从最基本的方波开始,逐一实现芯片音乐的核心波形。理解数字波形生成的原理,学会用计数器和状态机构造不同波形。
让波形"活"起来——控制频率播放不同音符,添加包络控制音量变化,加入颤音和滑音等表现力效果。
深入FM(调频)合成技术,从2算子到4算子,理解算子算法选择,设计丰富的音色。这是最接近真实声音芯片的合成方式。
构建自动演奏系统——节拍时钟、音符序列器、模式序列器、鼓机、多通道混音。让你的音乐自动播放。
整合所有知识,构建完整的8位旋律播放器、CH1风格合成器、鼓机+旋律组合,最终完成芯片音乐工作站!
本课程使用以下工具链:
Verilator是一个开源的Verilog编译器和lint工具,它能帮助你:
--lint-only模式)# 语法检查
verilator --lint-only my_module.v
# 编译仿真
verilator -cc my_module.v --build --exe sim_main.cpp
./obj_dir/Vmy_module
在开始写代码之前,我们需要理解几个核心概念:
数字音频是通过在固定时间间隔对声波进行采样来表示的。采样率决定了每秒采样的次数。CD音质是44100Hz,而芯片音乐通常使用更低的采样率(如8000-32000Hz),这本身就是"芯片味"的来源之一。
每个采样点用多少位来表示振幅。8位深度提供256级音量(-128到127),4位只有16级。低比特深度产生量化噪声,这就是芯片音乐"颗粒感"的来源。
声音的频率决定了音高。A4音(标准音)= 440Hz。每升高一个八度,频率翻倍;每降低一个八度,频率减半。西方音乐将一个八度分为12个半音,每个半音的频率比是2^(1/12) ≈ 1.0595。
| 音符 | 频率(Hz) | 说明 |
|---|---|---|
| C4 | 261.63 | 中央C |
| D4 | 293.66 | |
| E4 | 329.63 | |
| F4 | 349.23 | |
| G4 | 392.00 | |
| A4 | 440.00 | 标准音 |
| B4 | 493.88 | |
| C5 | 523.25 | 高八度C |
方波(Square Wave)是芯片音乐最标志性的波形。它只有两个电平值(高和低),在高低之间瞬间切换。这种"硬"切换产生丰富的奇次谐波,听起来明亮、锋利、充满电子感。
方波的傅里叶级数展开为:
f(t) = (4A/π) × [sin(ωt) + sin(3ωt)/3 + sin(5ωt)/5 + ...]
只包含奇次谐波(1次、3次、5次...),没有偶次谐波。这赋予了方波独特的"空心"音色,与锯齿波(包含所有谐波)形成鲜明对比。
方波的占空比(Duty Cycle)影响音色:50%占空比只有奇次谐波,25%或12.5%占空比则引入偶次谐波,音色更薄更尖锐。NES的2A03芯片就支持4种占空比切换,这是它的标志性音色之一。
verilator --lint-only确认安装成功芯片音乐入门者 — 完成第一课,理解芯片音乐的历史和技术基础,成功编译第一个方波发生器模块!
// square_wave_demo.v - 方波演示模块
// 基础方波发生器:用计数器翻转输出
module square_wave_demo #(
parameter CLK_FREQ = 50000000, // 50MHz时钟
parameter FREQ = 440 // A4音 = 440Hz
)(
input wire clk,
input wire rst_n,
output reg wave_out
);
// 计算半周期计数值
localparam HALF_PERIOD = CLK_FREQ / (2 * FREQ);
reg [31:0] counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 32'd0;
wave_out <= 1'b0;
end else begin
if (counter >= HALF_PERIOD - 1) begin
counter <= 32'd0;
wave_out <= ~wave_out;
end else begin
counter <= counter + 32'd1;
end
end
end
endmodule
✅ Verilator验证通过
从1970年代到1990年代,声音芯片经历了从简单蜂鸣器到复杂波表合成的飞速发展:
| 年代 | 芯片 | 突破 | 代表作品 |
|---|---|---|---|
| 1977 | AY-3-8910 | 3声道PSG | Pac-Man, Ghosts'n Goblins |
| 1981 | TI SN76489 | 4声道PSG | ColecoVision, SMS |
| 1982 | SID 6581 | 3声道+滤波器 | C64游戏/演示 |
| 1983 | 2A03 (RP2A03) | 5声道+DPCM | 超级马里奥, 塞尔达 |
| 1985 | YM2151 (OPM) | 8通道FM | X68000 |
| 1988 | YM2612 (OPN2) | 6通道FM+DAC | Mega Drive/Genesis |
| 1989 | DMG-CPU | 4声道+波表 | 俄罗斯方块, 宝可梦 |
| 1990 | S-SMP (SPC700) | 8通道采样 | 超任/SFC |
| 1995 | PS1 SPU | 24通道ADPCM | PS1游戏 |
虽然声音芯片早已被CD音质采样取代,但芯片音乐从未消失:
在AI生成音乐的时代,芯片音乐仍然有独特价值:
# Ubuntu/Debian 安装 Verilator
sudo apt install verilator
# 验证安装
verilator --version
# 创建项目目录
mkdir -p chiptune/verilog
cd chiptune
# 第一个验证命令
verilator --lint-only verilog/square_wave_demo.v
建议的编辑器配置:
芯片音乐不仅是技术产物,更是一种文化现象:
理解声音芯片的内部结构有助于我们设计Verilog实现:
┌────────────────────────────────────────┐
│ 声音芯片内部 │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ CH1 │ │ CH2 │ │ CH3 │ │
│ │振荡器│ │振荡器│ │振荡器│ │
│ │+包络 │ │+包络 │ │+包络 │ │
│ └──┬───┘ └──┬───┘ └──┬───┘ │
│ │ │ │ │
│ └────┬────┴────┬────┘ │
│ ▼ ▼ │
│ ┌─────────┐ ┌──────┐ │
│ │ 混音器 │ │ DAC │ → 音频输出 │
│ └─────────┘ └──────┘ │
│ │
│ ┌──────────────────────────────┐ │
│ │ 寄存器接口 (CPU读写) │ │
│ └──────────────────────────────┘ │
└────────────────────────────────────────┘
我们的Verilog实现将遵循同样的模块化结构——每个通道是独立的模块,混音器是公共模块,寄存器接口用于参数配置。
理解模拟音频与数字音频的转换是芯片音乐的基石:
要完美重建一个最高频率为f的信号,采样率必须≥2f。
人耳听觉范围: 20Hz - 20,000Hz
CD采样率: 44,100Hz (略高于2×20,000)
NES 2A03等效采样率: ≈44,700Hz (CPU时钟/周期)
Game Boy: ≈4,194,304Hz (系统时钟直接输出)
FPGA 50MHz时钟 → 等效采样率50MHz
→ 远超可听范围,但输出需要降采样到DAC采样率
在深入芯片音乐实现之前,理解一些DSP基础概念会让后续课程更容易理解:
| 概念 | 定义 | 在芯片音乐中的体现 |
|---|---|---|
| 采样 | 将连续信号离散化 | 每个时钟周期输出一个8位值 |
| 量化 | 用有限位数表示振幅 | 8位=256级,4位=16级 |
| 混叠 | 采样率不足导致的频谱折叠 | 8位系统中的"味道" |
| FFT | 快速傅里叶变换,分析频谱 | 理解波形谐波结构的工具 |
| 滤波 | 选择性通过/阻止某些频率 | 减法合成的核心操作 |
| 调制 | 用一个信号控制另一个信号的参数 | FM合成、颤音、震音 |
从软件思维转换到硬件思维是学习Verilog的关键:
| 概念 | 软件思维 | 硬件思维 |
|---|---|---|
| 执行 | 顺序执行,一次一步 | 并行执行,所有同时 |
| 时间 | CPU周期 | 时钟周期 |
| 变量 | 内存中的值 | 寄存器/线网 |
| 循环 | for/while | 计数器+状态机 |
| 数组 | 内存块 | ROM/RAM |
| 函数 | 调用返回 | 模块例化 |
| 延时 | sleep()调用 | 流水线级/计数器 |
| 乘法 | 单条指令 | DSP单元或移位加法 |
本课程使用的Verilog特性清单: