基于 FPGA 的 SD 卡音频播放与电子琴系统

基于 FPGA 的 SD 卡音频播放与电子琴系统

一、项目概述

(可做实物一套(含代码,讲解,仿真),需要实物请联系QQ:1391074994)

本项目实现了一个基于 Intel Cyclone IV E FPGA 的 SD 卡音频播放系统,同时兼具电子琴功能。核心功能包括:

  • 电子琴演奏:通过 10 个按键(7 音阶 + 低/中/高音切换),使用 DDS 合成正弦波,驱动 WM8978 音频芯片实时发声
  • SD 卡录音/回放:将弹奏的音频存入 SD 卡,支持从 SD 卡读取并回放已录制的音频
  • 人机交互:OLED 128x32 显示屏显示当前音阶编号与音域,21 个 LED 指示当前音符频率

硬件平台

  • FPGA 芯片:Intel Cyclone IV E 系列
  • 音频芯片:WM8978(I2C 配置 + I2S 数据传输)
  • 存储介质:SD 卡(SPI 模式)
  • 显示模块:OLED 128x32(SPI 接口)
  • 输入设备:10 个按键

二、工程文件结构

复制代码
rtl/
├── top_audio_sd.v          # 顶层模块(系统集成)
├── top_audio_sd_tb.v       # 仿真测试平台
├── audio_sd_ctrl.v         # SD卡音频交互控制
├── data_gen.v              # 音频数据生成与FIFO中转
├── led.v                   # 21个LED指示灯控制
│
├── fifo/
│   └── async_fifo.v        # 异步FIFO(通用参数化模块)
│
├── key/
│   ├── key_debounce.v      # 按键消抖
│   ├── key_top.v           # 8按键顶层处理
│   ├── dds_sin.qip         # DDS正弦波ROM IP索引
│   └── pll_clk.qip         # PLL时钟模块IP索引
│
├── sd/
│   ├── sd_ctrl_top.v       # SD卡顶层控制
│   ├── sd_init.v           # SD卡SPI初始化
│   ├── sd_read.v           # SD卡SPI读数据
│   └── sd_write.v          # SD卡SPI写数据
│
├── wm8978/
│   ├── wm8978_ctrl.v       # WM8978总控模块
│   ├── wm8978_config.v     # WM8978配置顶层
│   ├── i2c_dri.v           # I2C驱动
│   ├── i2c_reg_cfg.v       # WM8978寄存器配置
│   ├── audio_send.v        # I2S音频发送
│   └── audio_receive.v     # I2S音频接收
│
├── wave/
│   ├── wave_ctrl.v         # 频率控制核心
│   ├── da_wave_send.v      # DDS正弦波发生器
│   ├── time_send.v         # 时序控制/回放调度
│   └── sd_wr_ctrl.v        # SD卡读写测试控制
│
└── oled/
    └── OLED12832.v         # OLED 128x32 显示驱动

三、顶层模块架构

top_audio_sd(顶层集成模块)

参数

参数 说明
sim 0/1 仿真模式开关(1 = 仿真)
START_ADDR 8256 SD 卡起始扇区地址
AUDIO_SEC 79076 录音最大扇区数

时钟域

时钟 频率 用途
clk 50MHz 系统主时钟
pll_clk_sd 25MHz SD 卡 SPI 时钟
pll_clk_aud 12.288MHz WM8978 主时钟(MCLK)
aud_bclk ~3.072MHz I2S 位时钟(WM8978 MASTER 模式)

子模块连接图

复制代码
                          ┌─────────────────────────┐
                          │        top_audio_sd      │
                          │                          │
  key_in[3:0] ──────────►│  key_top (功能键)         │
  key_in[9:4] ──────────►│  key_top (7音阶键)        │
  key_in[15:10] ────────►│  key_top (音域键)         │
                          │                          │
                          │  wave_ctrl ──► da_wave_send ──┤
                          │      │                        │
                          │      ▼                        ▼
                          │   fre_show ────► OLED12832   dac_data ──► wm8978_ctrl
                          │   fre_show ────► led           │
                          │                  │            │
                          │  time_send      data_gen      │
                          │  (回放调度) ◄──► (FIFO中转)    │
                          │      │            │           │
                          │      ▼            ▼           │
                          │   sd_ctrl_top ──── SD卡        │
                          │  (SPI读写)                     │
                          └─────────────────────────┘

四、子系统详细说明

4.1 时钟系统

  • 系统时钟 clk = 50MHz(由板载晶振提供)
  • 通过 PLLpll_clk 模块)产生:
    • pll_clk_sd = 25MHz:供 SD 卡 SPI 控制器使用
    • pll_clk_aud = 12.288MHz:WM8978 的 MCLK 主时钟
  • WM8978 工作在 MASTER 模式 ,产生 aud_bclkaud_lrc 信号

4.2 SD 卡子系统

模块层次sd_ctrl_topsd_init / sd_write / sd_read

sd_ctrl_top --- SD 卡顶层控制器
  • 根据 sd_init_donewr_busyrd_busy 选择对应子模块的接口信号
  • 优先顺序:初始化 > 写 > 读
  • 输入 25MHz 时钟,SPI 接口工作频率约 125KHz(DIV_FREQ=200)
sd_init --- SD 卡 SPI 初始化
  • 状态机流程:上电等待(5000 周期) → CMD0(复位) → CMD8(电压检测 2.7~3.6V) → CMD55 → ACMD41(循环等待直到就绪,超时 25000 周期)
  • 初始化完成后拉高 sd_init_done
sd_write --- SD 卡 SPI 写数据
  • 发送 CMD24(WRITE_BLOCK)单块写命令
  • 数据格式:起始字节 0xFE + 512 字节数据(256×16bit)+ 2 字节 CRC
  • 等待 BUSY 信号释放后完成
sd_read --- SD 卡 SPI 读数据
  • 发送 CMD17(READ_SINGLE_BLOCK)单块读命令
  • 等待响应(0x00)和起始字节(0xFE)
  • 接收 512 字节数据(256×16bit),输出 rd_val_datard_val_en

关键扇区地址

参数 说明
START_ADDR 8256 录音数据起始扇区
AUDIO_SEC 79076 录音最大扇区数

4.3 WM8978 音频子系统

模块层次wm8978_ctrlwm8978_config + audio_send + audio_receive

wm8978_config --- 寄存器配置
  • 例化 i2c_dri(I2C 驱动)和 i2c_reg_cfg(寄存器配置表)
  • 配置完成后拉高 cfg_done
i2c_dri --- I2C 驱动
  • 从机地址 0x34(7-bit) → 0x34 << 1 = 0x68(8-bit)
  • 三段式状态机:IDLE → 发送从机地址 → 发送寄存器地址(8/16位) → 写数据 / 读数据 → STOP
  • I2C 时钟频率 250KHz(50MHz / 200)
i2c_reg_cfg --- WM8978 寄存器配置表

配置 17 个寄存器:

寄存器 功能 关键值
R0 (0x00) 软复位 0x0000
R1 (0x01) 电源管理1 使能 BIASEN, VMIDSEL1:0
R2 (0x02) 电源管理2 使能 DACL, DACR, LOUT1, ROUT1
R3 (0x03) 电源管理3 使能 RMIX, LMIX, LOUT2, ROUT2, RMIC, LMIC
R4 (0x04) 音频接口 I2S 16bit, 格式
R6 (0x06) 时钟生成 MCLK / 采样率分频
R7 (0x07) 附加控制 MASTER 模式
R10 (0x0A) DAC 控制 DAC 软静音控制
R43 (0x2B) 左输入控制 0x0100
R44 (0x2C) 右输入控制 0x0100
R47 (0x2F) 左输出混合 0x0100
R48 (0x30) 右输出混合 0x0100
R49 (0x31) 左输出音量 0x0139
R50 (0x32) 右输出音量 0x0139
R51 (0x33) 左耳机输出 0x0100 + PHONE_VOLUME(20)
R52 (0x34) 右耳机输出 0x0100 + PHONE_VOLUME(20)
R53 (0x35) 左喇叭混合 0x0100 + SPEAK_VOLUME(40)
R54 (0x36) 右喇叭混合 0x0100 + SPEAK_VOLUME(40)
audio_send --- I2S 音频发送
  • 字长 WL = 16bit
  • aud_lrc 边沿加载 dac_data,串行输出到 aud_dacdat
  • 发送完成输出 tx_done
audio_receive --- I2S 音频接收
  • 字长 WL = 32bit
  • aud_adcdat 采集音频数据,输出 adc_data[31:0]

4.4 电子琴子系统(波形生成)

模块层次key_topwave_ctrlda_wave_send

key_top --- 按键顶层
  • 例化 8 个 key_debounce 消抖模块
  • 消抖参数:20ms(500000 周期 @ 50MHz),仿真模式 100 周期
  • 输出:按键按下瞬间的单周期脉冲 key_data_1~8
key_debounce --- 按键消抖
  • 检测按键状态变化后启动 20ms 倒计时
  • 计数器归零后采样稳定值,输出 key_flagkey_value
wave_ctrl --- 频率控制核心
  • 按键映射:10 个按键 → 21 个音符频率
按键组 功能
func_key[3:0] 功能选择(4按键)
play_key[3:0] 7 个音阶按键(Do/Re/Mi/Fa/Sol/La/Si)
tone_key[3:0] 低音 / 中音 / 高音 切换
  • 21 个音符频率表(对应低/中/高三个音域):
音阶 低音 中音 高音
Do 262Hz 523Hz 1046Hz
Re 294Hz 587Hz 1174Hz
Mi 330Hz 659Hz 1319Hz
Fa 349Hz 698Hz 1397Hz
Sol 392Hz 784Hz 1568Hz
La 440Hz 880Hz 1760Hz
Si 494Hz 988Hz 1976Hz
  • 频率控制字计算freq_data = fre_act * 85
  • 回放模式下从 audio_data_rd 获取频率信息
  • 输出 fre_show 用于 OLED 和 LED 显示
da_wave_send --- DDS 正弦波发生器
  • 相位累加器:phase_addr + freq_data(频率控制字)
  • dds_sin ROM(4096×8bit)中查表输出正弦波数据
  • send_flag 控制输出使能
  • 输出 da_data[7:0] 送至 WM8978 DAC

4.5 音频数据交互子系统

模块data_gen + audio_sd_ctrl

data_gen --- 数据生成与中转
  • 例化两个异步 FIFO:
    • u_async_fifo_audio_save:弹奏音频 → FIFO → SD 卡写
    • u_async_fifo_audio_play:SD 卡读 → FIFO → 回放播放
  • 数据位宽 16bit,深度参数化(仿真模式使用较小深度)

核心逻辑

  1. 录音模式 :用户弹奏时,audio_data_wr_vld 触发数据存入 save FIFO,fifo 数据计数达到阈值后向 SD 卡写一个扇区
  2. 回放模式 :从 SD 卡读取扇区数据存入 play FIFO,根据 read_speed 控制读取速率,输出 audio_data_rd
audio_sd_ctrl --- SD 卡音频交互控制
  • 参数
    • START_ADDR = 8448(录音起始扇区)
    • AUDIO_SEC = 104422(录音扇区总数)
  • 状态机管理 SD 卡扇区读写调度
  • 生成 DAC 数据输出,控制 FIFO 写入计数
time_send --- 时序/回放控制
  • 参数 NUM_DATA = 255
  • 按键触发检测 :11 级移位寄存器实现消抖,输出 touch 脉冲
  • time_cnt 倒计时管理音频播放时长
  • 100ms 定时生成 audio_data_rd_req 信号
  • 支持 read_speed 加速回放机制

4.6 显示子系统

OLED12832 --- OLED 显示驱动
  • 分辨率 128×32 像素
  • 内置 5×8 点阵 ASCII 字库(0-9, A-Z, a-z 及特殊符号)
  • 状态机:MAIN → INIT → SCAN → WRITE → DELAY
  • 显示内容:
    • 当前音阶编号(0~20)
    • 音域状态(低/中/高音,用 "LOW"/"MED"/"HIG" 标识)
  • SPI 4 线接口(DC, SDA, SCL, RES, CS)
led --- LED 指示灯
  • 21 个 LED,对应 21 个音符频率
  • fre_show 匹配某个预定义的频率值时,对应 LED 通过 send_flag 闪烁
  • 支持频率值:262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 698, 784, 880, 988, 1046, 1174, 1319, 1397, 1568, 1760, 1976

4.7 测试/仿真

top_audio_sd_tb --- 仿真测试平台
  • 提供 50MHz 主时钟(周期 20ns)
  • 复位信号持续 2000ns 后释放
  • 仿真按键操作:
    • key_play_10 按键(中音 Do):按 8ms + 松 20ms + 按 4ms + 松 20ms
    • key_play_7 按键(Si):按 4ms + 松 30ms + 按 4ms
  • 总仿真时间 100ms(5000000 个时钟周期)
sd_wr_ctrl --- SD 卡读写测试
  • sd_init_done 上升沿触发
  • 写操作:向扇区 2000 写入递增数据
  • 读操作:读回扇区 2000 数据并校验
  • 数据校验失败时拉高 error_flag
  • 仅在仿真模式下可通过 sim 参数选择内部模块连接到此控制器

五、时钟域与接口信号汇总

时钟域分布

模块 时钟信号 频率
top_audio_sd clk 50MHz
sd_ctrl_top / SD 子系统 pll_clk_sd 25MHz
wm8978_ctrl / 音频子系统 clk + aud_bclk 50MHz + ~3.072MHz
data_gen FIFO(写端) clk 50MHz
data_gen FIFO(读端) pll_clk_sd 25MHz

顶层端口列表

端口名 方向 位宽 功能
clk input 1 系统主时钟 50MHz
rst_n input 1 异步复位(低有效)
key_in input 16 16 个按键输入
sd_mosi output 1 SD 卡 SPI MOSI
sd_miso input 1 SD 卡 SPI MISO
sd_clk output 1 SD 卡 SPI 时钟
sd_cs output 1 SD 卡 SPI 片选
aud_bclk input 1 I2S 位时钟
aud_lrc input 1 I2S 左右声道
aud_dacdat output 1 I2S DAC 数据
aud_adcdat input 1 I2S ADC 数据
i2c_sda inout 1 I2C 数据线
i2c_scl output 1 I2C 时钟线
olcd_cs output 1 OLED 片选
olcd_dc output 1 OLED 数据/命令
olcd_scl output 1 OLED SPI 时钟
olcd_sda output 1 OLED SPI 数据
olcd_res output 1 OLED 复位
led output 4 LED 指示输出

六、系统工作流程

6.1 上电初始化

复制代码
上电
 ├─ PLL 锁定 → 产生 sd_clk / aud_clk
 ├─ WM8978 初始化:I2C 配置 17 个寄存器
 ├─ SD 卡初始化:SPI 模式 CMD0→CMD8→CMD55→ACMD41
 └─ OLED 初始化:写入配置命令 → 显示开机画面

6.2 电子琴演奏模式

复制代码
按键按下 → key_top 消抖 → 单脉冲输出
 └─ wave_ctrl:按键组合 → 查表得频率 → 计算 freq_data
      └─ da_wave_send:DDS 累加 → ROM 查表 → da_data
           └─ wm8978_ctrl:audio_send → I2S 发送 → WM8978 DAC → 发声
      └─ fre_show → OLED 显示音阶 / LED 指示音符

6.3 录音流程(弹奏 → SD 卡)

复制代码
弹奏 → audio_data_wr_vld → 数据存入 save FIFO
 └─ data_gen:FIFO 数据量 ≥ 256 → wr_start_en
      └─ sd_write:CMD24 → SPI 写入 512 字节 → wr_busy 释放
           └─ wr_sec_addr++

6.4 回放流程(SD 卡 → 播放)

复制代码
time_send:检测回放按键 → touch 触发 → audio_data_rd_req
 └─ data_gen:FIFO 空 → rd_start_en
      └─ sd_read:CMD17 → SPI 读取 512 字节 → 存入 play FIFO
           └─ FIFO → audio_data_rd → wave_ctrl → da_wave_send → 发声

七、关键参数汇总

模块 参数 说明
top_audio_sd START_ADDR 8256 录音起始扇区
top_audio_sd AUDIO_SEC 79076 最大录音扇区数
audio_sd_ctrl START_ADDR 8448 音频控制起始扇区
audio_sd_ctrl AUDIO_SEC 104422 音频控制扇区总数
sd_init DIV_FREQ 200 SPI 时钟分频(250KHz)
sd_init POWER_ON_NUM 5000 上电等待周期
sd_init OVER_TIME_NUM 25000 ACMD41 超时周期
i2c_dri SLAVE_ADDR 0x34 WM8978 I2C 地址
i2c_dri CLK_FREQ 50MHz 驱动时钟频率
i2c_dri I2C_FREQ 250KHz I2C 总线频率
i2c_reg_cfg REG_NUM 17 配置寄存器数量
i2c_reg_cfg PHONE_VOLUME 20 耳机音量
i2c_reg_cfg SPEAK_VOLUME 40 喇叭音量
audio_send WL 16 I2S 发送字长
audio_receive WL 32 I2S 接收字长
time_send NUM_DATA 255 回放数据计数
key_debounce 消抖时间 20ms @50MHz = 1000000 ticks
da_wave_send ROM 4096×8bit 正弦波查找表
async_fifo DATA_WIDTH 16 数据位宽
async_fifo FIFO_DEPTH 256/自定义 FIFO 深度

八、外部 IP 核依赖

IP 核 文件 功能
PLL 锁相环 pll_clk 50MHz → 25MHz + 12.288MHz
DDS ROM dds_sin 4096×8bit 正弦波查找表,初始化文件 dds_4096x8b_wave_sin.mif
FIFO async_fifo_ip 异步 FIFO,数据中转缓冲

九、开发环境

  • FPGA 器件:Intel Cyclone IV E(EP4CE 系列)
  • 开发工具:Quartus Prime / Quartus II
  • 仿真工具:ModelSim(仿真文件中使用 $display 打印调试信息)
  • 硬件平台:正点原子 FPGA 开发板

十、注意事项

  1. 跨时钟域处理data_gen 中 FIFO 写端使用 50MHz,读端使用 25MHz(SD 卡时钟),通过异步 FIFO 实现可靠跨时钟域传输
  2. SD 卡格式:需使用 FAT32 格式化,音频数据存储在指定扇区偏移位置(起始扇区 8256)
  3. 仿真模式top_audio_sdsim 参数 = 1 时,sd_wr_ctrl 替换 audio_sd_ctrl 进行 SD 卡读写功能测试
  4. 参数一致性top_audio_sdaudio_sd_ctrl 中的扇区参数不同,请在整合同一个系统时确认正确的参数值
  5. WM8978 主从模式:当前配置 WM8978 为 MASTER 模式,由 WM8978 提供 BCLK 和 LRC。如需改为 SLAVE 模式,需修改 R7 寄存器配置
相关推荐
毕设源码_郑学姐18 小时前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
qq_2518364571 天前
2026计算机毕设选题|3000套高质量SpringBoot实战项目(含完整源码)(每人一套不收米)
java·spring boot·课程设计
点灯小铭1 天前
基于单片机的雨量检测智能汽车雨刮器模拟系统设计与实现
单片机·嵌入式硬件·汽车·毕业设计·课程设计·期末大作业
chenlance1 天前
基于FPGA的激光器多通道数据采集与波形控制系统设计
fpga开发
清风6666661 天前
基于单片机与12864显示屏的多种函数波形信号发生器设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
羊羊小栈1 天前
停车场管理系统(基于前后端Web开发)
前端·人工智能·毕业设计·大作业
点灯小铭1 天前
基于51单片机的LED点阵汉字显示系统设计
数据库·单片机·嵌入式硬件·毕业设计·51单片机·课程设计·期末大作业
9527华安1 天前
FPGA实现GTP高速收发器2路视频传输,基于aurora 8b10b编解码架构,提供4套工程源码和技术支持
图像处理·fpga开发·aurora·高速收发器·8b10b·derdes
cjie2211 天前
lanczos插值引起的振铃现象
计算机视觉·fpga开发
清风6666661 天前
基于单片机的多路自动投食机设计与智能语音喂养系统
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业