我的FPGA毕业设计:一款支持歌词同步的智能音乐播放器(附完整代码)

 首先先声明一下,本项目已经结题,可以放心根据我的设计进行二次开发和直接套用!!!

代码每行都标有注释,方便同学进行学习!!

制作不易,记得三连哦,给我动力,持续更新!!!

完整工程文件下载:基于FPGA的音乐播放完整工程下载 (点击蓝色字体获取)

 


引言

        随着数字信号处理和嵌入式系统技术的发展,基于现场可编程门阵列(FPGA)的音乐播放器因其高灵活性和实时处理能力受到广泛关注。本文介绍了一种基于Altera Cyclone IV系列FPGA芯片EP4CE10F17C8的MP3音乐播放器设计。该设计能够从SD卡读取并播放MP3或者WAV格式的音乐文件,通过按键实现播放控制(暂停/播放、切歌、音量调节、单曲循环与顺序播放切换),通过LCD显示歌名(歌名图片存储于另一张SD卡),并支持通过蓝牙模块实现上一曲/下一曲控制。整个系统使用Verilog硬件描述语言实现,兼顾性能与功能扩展性。

本文旨在分享设计过程、实现细节及遇到的问题与解决方案,为FPGA开发者提供参考,也可以找我进行二次设计和其他FPGA设计指导。

关键词:FPGA;MP3硬件解码;音频处理;Verilog HDL;LCD显示

 

一、系统设计概述

本音乐播放器系统的设计目标是实现一个功能完整、操作简便的嵌入式音乐播放器。系统整体架构分为硬件和软件两部分

1.1 系统功能

  1. 音乐播放:从SD卡读取MP3文件并解码播放。
  2. 按键控制:支持暂停/播放、切歌、音量加减、单曲循环与顺序播放切换。
  3. LCD显示:显示当前播放歌曲的歌名(歌名以图片形式存储于另一张SD卡)。
  4. 蓝牙控制:通过蓝牙模块实现上一曲/下一曲切换。
  5. 开发平台:基于Altera EP4CE10F17C8 FPGA,使用Verilog语言。

1.2 系统架构

系统由以下模块组成:

  • SD卡接口模块:负责读取主SD卡中的MP3文件和辅助SD卡中的歌名图片。
  • MP3解码模块:解码MP3音频数据并输出至音频接口。
  • 音频输出模块:将解码后的音频数据转换为模拟信号输出至扬声器或耳机。
  • 按键控制模块:处理用户按键输入,实现多种控制功能。
  • LCD显示模块:驱动LCD屏幕显示歌名图片。
  • 蓝牙通信模块:接收蓝牙信号,实现远程切歌控制。
  • 主控模块:协调各模块的工作,管理数据流和控制信号。

具体的实现框架如下图所示:

 

二、硬件设计

2.1 主要硬件组件

  1. FPGA芯片:Altera Cyclone IV EP4CE10F17C8,逻辑单元约10K,适合中小型嵌入式应用。
  2. SD卡模块
    • 主SD卡:存储MP3音乐文件,支持FAT32文件系统。
    • 辅助SD卡:存储歌名图片(BMP或JPEG格式)。
  3. 音频解码芯片:MY690-16S解码芯片,支持MP3格式解码和音频输出。
  4. LCD显示屏:TFT LCD 液晶屏模块 4.3 寸LCD,用于显示歌名图片。
  5. 蓝牙模块:HC-05蓝牙模块,支持串口通信,接收控制指令。
  6. 按键:5个按键(播放/暂停、下一曲、上一曲、音量加、音量减)。
  7. 音频输出:8R喇叭扬声器

2.2 硬件介绍

2.2.1 FPGA介绍

        本设计FPGA部分没有进行硬件画板子设计,正好我手里有一个开发板就直接使用了,采用的是宏图pro开发板,该开发板正好可以满足我这次设计的所以外设,并且资源够用,如果大家没有这个开发板的话,也可以随便找一个你自己的开发板,工程可以完全移植

2.2.2 LCD介绍

        本次设计LCD显示屏,我才用的是黑金的配套4.3" TFT LCD 液晶屏模块 AN430 模块,这个也是我之前设计一直在使用的模块,大家如果有别的也可以替代使用

2.2.4 SD卡模块

        本设计的SD卡读写模块,采用的最常用的,而且最便宜的SD卡读写模块,大家可以自行在某宝进行购买,大概也就几块钱,读写的协议采用的是SPI协议

2.2.5 音频模块

本设计的音频模块采用的是MY1690-12P模块进行设计,此模块采用串口的方式进行读写,使用起来非常方便,大家也可自行准备

2.2.6 音频播放模块

本设计的音频播放模块,也是采用最简单的喇叭进行播放,主打一个经济实惠,但是设计完全没问题的原则,大家也可以自行准备

2.2.7 蓝牙模块

        本设计的蓝牙模块采用的是HC-05蓝牙模块,也是大家经常使用的模块,之前很多设计都有用到,所以也没必要再换别的模块

三、设计思路

3.1 整体设计

        本设计为多功能数字音乐播放器设计,采用FPGA作为核心控制整个电路,预期对需要的功能绘制流程图和各个子模块框图,导出数据通道和控制单元,编写Verilog代码,对代码进行仿真和验证。   

        整个系统设计分为音乐处理模块(mp3_top),蓝牙控制模块(lanya_ctrl),SD卡控制模块(sd_ctrl),sdram模块(sdram_top),LCD显示模块(tft_ctrl)以及图片选择模块(data_rd_ctrl)。

3.1.1 音乐处理模块

音乐模块的硬件原理图如下所示:

其中我们可以通过串口进行 音乐的选择、播放、工作模式进行设置,具体的协议如下所示

3.1.2 蓝牙模块设计

蓝牙模块主要工作原理也是通过串口给FPGA发生数据,让后由安卓手机作为主机,进行数据发送

3.1.3 SD卡读写模块

SD卡读写模块主要是使用SPI协议对SD模块进行图片的读取,其中SD卡主要的时许图如下所示

通过控制读写的地址,来切换显示的具体的音乐名称

四、代码设计

本次设计的代码全部使用verilog进行实现,开发平台为Quartus II 13.0,我将分开给大家介绍实现的代码

4.1 音乐处理模块(mp3_top)

此代码的功能为用FPGA接收按键操作,通过串口控制MP3模块播放,同时管理播放状态和曲目显示。

部分代码如下:

module mp3_top(
			input 			clk_50m,	//外部输入50mHz时钟信号
			input			uart_rx_pc,
			output			uart_tx_pc,
					
			input			uart_rx_mp3,
			output			uart_tx_mp3,
			input			key_up,
			input			key_down,
			input			key_audio_add,
			input			key_audio_sub,
			input			key_pause,
			output	[3:0]	music_num,
			output			music_num_vld
		);														
//wire	uart_tx;
//-------------------------------------
wire bps_start1;	//接收到数据后,波特率时钟启动信号置位
wire clk_bps1;		// clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点 
wire[7:0] rxdb;	//串口接收数据
wire rxen;		//串口接收数据有效标志位,高电平一个时钟周期
wire[7:0] txdb;	//串口发送数据
wire txen;		//串口发送数据有效标志位,高电平一个时钟周期
wire[7:0]	uart_rx_data;

4.2 蓝牙控制模块(lanya_ctrl)        

这个模块是 蓝牙串口通信的接收端,负责解码手机发来的控制指令,供FPGA主控使用。

部分代码如下所示:

always@(posedge clk)
   if(~rst_n)begin
    rx_reg1<=1;
    rx_reg2<=1;
    end
   else  begin
    rx_reg1<=rx;
    rx_reg2<=rx_reg1;
end
always@(posedge clk)
    if(~rst_n)
        en_rx<=0;
    else if(flag_n)
        en_rx<=1;
    else if(done)
        en_rx<=0;

always@(posedge clk)
    if(~rst_n)
        cnt_bps<=0;
    else if(en_rx==1)begin
        if(cnt_bps==delay-1)
            cnt_bps<=0;
        else
        cnt_bps<=cnt_bps+1;
    end
        
always@(posedge clk)
    if(~rst_n)
        cnt_bit<=0;
        else if(done)
        cnt_bit<=0; 
    else if(cnt_bps==delay-1)
        cnt_bit<=cnt_bit+1;   
        
   always@(posedge clk)
    if(~rst_n)
        data_reg<=0;

    else if(cnt_bit>0&&cnt_bit<9&&cnt_bps==delay/2-1)
        data_reg[cnt_bit-1]<=rx_reg2;
    else if(done)
        data_reg<=0;

4.3 SD卡控制模块(sd_ctrl)

此代码主要是控制SD卡读写图片信息,并通过sdram进行缓存,其中包括初始化SD卡,读取SD卡扇区和指定地址

部分代码如下:

module  sd_ctrl
(
    input   wire            sys_clk         ,   //输入工作时钟,频率50MHz
    input   wire            sys_clk_shift   ,   //输入工作时钟,频率50MHz,相位偏移90度
    input   wire            sys_rst_n       ,   //输入复位信号,低电平有效
    //SD卡接口
    input   wire            sd_miso         ,   //主输入从输出信号
    output  wire            sd_clk          ,   //SD卡时钟信号
    output  reg             sd_cs_n         ,   //片选信号
    output  reg             sd_mosi         ,   //主输出从输入信号
    //写SD卡接口
    input   wire            wr_en           ,   //数据写使能信号
    input   wire    [31:0]  wr_addr         ,   //写数据扇区地址
    input   wire    [15:0]  wr_data         ,   //写数据
    output  wire            wr_busy         ,   //写操作忙信号
    output  wire            wr_req          ,   //写数据请求信号
    //读SD卡接口
    input   wire            rd_en           ,   //数据读使能信号
    input   wire    [31:0]  rd_addr         ,   //读数据扇区地址
    output  wire            rd_busy         ,   //读操作忙信号
    output  wire            rd_data_en      ,   //读数据标志信号
    output  wire    [15:0]  rd_data         ,   //读数据

    output  wire            init_end            //SD卡初始化完成信号
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire            init_cs_n   ;   //初始化阶段片选信号
wire            init_mosi   ;   //初始化阶段主输出从输入信号
wire            wr_cs_n     ;   //写数据阶段片选信号
wire            wr_mosi     ;   //写数据阶段主输出从输入信号
wire            rd_cs_n     ;   //读数据阶段片选信号
wire            rd_mosi     ;   //读数据阶段主输出从输入信号

4.4 sdram模块(sdram_top)

此模块主要是用来缓存SD卡读取的数据,并传送到LCD显示模块

主要代码如下:

module  sdram_top
(
    input   wire            sys_clk         ,   //系统时钟
    input   wire            clk_out         ,   //相位偏移时钟
    input   wire            sys_rst_n       ,   //复位信号,低有效
//写FIFO信号
    input   wire            wr_fifo_wr_clk  ,   //写FIFO写时钟
    input   wire            wr_fifo_wr_req  ,   //写FIFO写请求
    input   wire    [15:0]  wr_fifo_wr_data ,   //写FIFO写数据
    input   wire    [23:0]  sdram_wr_b_addr ,   //写SDRAM首地址
    input   wire    [23:0]  sdram_wr_e_addr ,   //写SDRAM末地址
    input   wire    [9:0]   wr_burst_len    ,   //写SDRAM数据突发长度
    input   wire            wr_rst          ,   //写复位信号
//读FIFO信号
    input   wire            rd_fifo_rd_clk  ,   //读FIFO读时钟
    input   wire            rd_fifo_rd_req  ,   //读FIFO读请求
    input   wire    [23:0]  sdram_rd_b_addr ,   //读SDRAM首地址
    input   wire    [23:0]  sdram_rd_e_addr ,   //读SDRAM末地址
    input   wire    [9:0]   rd_burst_len    ,   //读SDRAM数据突发长度
    input   wire            rd_rst          ,   //读复位信号
    output  wire    [15:0]  rd_fifo_rd_data ,   //读FIFO读数据
    output  wire    [9:0]   rd_fifo_num     ,   //读fifo中的数据量

    input   wire            read_valid      ,   //SDRAM读使能
    input   wire            pingpang_en     ,   //SDRAM乒乓操作使能
    output  wire            init_end        ,   //SDRAM初始化完成标志
//SDRAM接口信号

4.5 LCD显示模块(tft_ctrl)

此模块主要读取sdram的图片数据,然后显示歌曲的名称图片,其中也包括初始化LCD和控制lcd显示的数据设计

代码如下:

module  tft_ctrl
(
    input   wire            clk_9m      ,   //输入时钟,频率9MHz
    input   wire            sys_rst_n   ,   //系统复位,低电平有效
    input   wire    [15:0]  data_in     ,   //待显示数据

    output  wire            data_req    ,   //数据请求信号
    output  wire    [15:0]  rgb_tft     ,   //TFT显示数据
    output  wire            hsync       ,   //TFT行同步信号
    output  wire            vsync       ,   //TFT场同步信号
    output  wire            tft_clk     ,   //TFT像素时钟
    output  wire            tft_de      ,   //TFT数据使能
    output  wire            tft_bl          //TFT背光信号
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//parameter     define
parameter   H_SYNC      =   11'd41  ,   //行同步
            H_BACK      =   11'd2   ,   //行时序后沿
            H_LEFT      =   11'd0   ,   //行时序左边框
            H_VALID     =   11'd480 ,   //行有效数据
            H_RIGHT     =   11'd0   ,   //行时序右边框
            H_FRONT     =   11'd2   ,   //行时序前沿
            H_TOTAL     =   11'd525 ;   //行扫描周期
parameter   V_SYNC      =   11'd10  ,   //场同步
            V_BACK      =   11'd2   ,   //场时序后沿
            V_TOP       =   11'd0   ,   //场时序左边框
            V_VALID     =   11'd272 ,   //场有效数据
            V_BOTTOM    =   11'd0   ,   //场时序右边框
            V_FRONT     =   11'd2   ,   //场时序前沿
            V_TOTAL     =   11'd286 ;   //场扫描周期

4.6 图片选择模块(data_rd_ctrl)

此代码主要是配合音乐的播放,来控制LCD显示的图片信息,通过音乐模块反馈的当前播放的音乐来控制LCD显示的音乐名称

代码如下:

module  data_rd_ctrl
(
    input   wire            sys_clk     ,   //输入工作时钟,频率50MHz
    input   wire            sys_rst_n   ,   //输入复位信号,低电平有效
    input   wire            rd_busy     ,   //读操作忙信号

	input			[3:0]	music_num,
	input					music_num_vld,
    output  reg             rd_en       ,   //数据读使能信号
    output  reg     [31:0]  rd_addr         //读数据扇区地址
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter   IDLE    =   3'b001  ,   //初始状态
            READ    =   3'b010  ,   //读数据状态
            WAIT    =   3'b100  ;   //等待状态
			
parameter   IMG_SEC_ADDR0   =   32'd25152,  //图片1扇区起始地址 dui
            IMG_SEC_ADDR1   =   32'd25664,  //图片2扇区起始地址
			IMG_SEC_ADDR2   =   32'd26176,  //图片2扇区起始地址
			IMG_SEC_ADDR3   =   32'd26688,  //图片2扇区起始地址
			IMG_SEC_ADDR4   =   32'd24640;  //图片2扇区起始地址
	

5、下板测试

连接好硬件设备,然后给开发板供电

编译工程,生成.sof文件,然后下载到FPGA开发板,进行测试,测试没问题后,固化.jjc文件到FPGA开发板。
硬件连接如下:

同时需要一个安卓手机,下载蓝牙调试助手,我就用之前小车的上进行修改,具体如下,只用到上一曲和下一曲的功能

具体演示如下面视频所示:

https://live.csdn.net/v/476912

基于FPGA的多功能音乐播放器

这样我们项目的完整功能就测试完毕,后期可根据需求在进行更新!!!

如果感觉文章对您有用,麻烦三连支持一下,方便下次用到的时候,就可以快速找到我,非常感谢您的支持!!!

完整工程文件下载:基于FPGA的音乐播放完整工程下载 (点击蓝色字体获取)

posted @ 2025-05-10 23:12  FPGAmaster  阅读(368)  评论(1)    收藏  举报