当前位置: 首页 > news >正文

基于fpga的串口控制的音乐播放器

基于fpga的串口控制的音乐播放器

  • 题目要求
  • 一、总体框架
  • 二、verilog代码
    • 1.串口驱动
    • 2.数码管驱动
    • 3.顶层模块
    • 4.蜂鸣器驱动


题目要求

要求:
通过串口接收要播放的音符,do、re、mi、fa、sol、la、ti和高音do分别用数字1~8表示
收到音符后自动播放,每个音符的音长为0.5s
可在播放的同时接收新的音符,支持单个和批量发送(同一时刻待播放的音符数不超过100个)
在六位七段数码管上显示播放的音符,当前播放的显示在最右侧,每播放一个新的音符较早的音符左移

一、总体框架

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
串口驱动-----数码管驱动------蜂鸣器pwm驱动-------数码管显示数据切换--------FIFO数据写入和读出

二、verilog代码

1.串口驱动

//****************************************Copyright (c)***********************************////****************************************************************************************//module uart_top(input            sys_clk  ,   //�ⲿ50MHzʱ��input            sys_rst_n,   //ϵ�ⲿ��λ�źţ�����Ч//UART�˿�   input            uart_rxd ,   //UART���ն˿�output           uart_txd ,    //UART���Ͷ˿�input            uart_tx_en,    //UART���������ź�output wire         uart_rx_done,    //UART���������ź�  output wire         uart_tx_done,    //UART���������ź�  input        [7:0]  uart_tx_data,    //UART��������     output wire  [7:0]  uart_rx_data    //UART��������         );//parameter define
parameter CLK_FREQ = 50000000;    //����ϵͳʱ��Ƶ��
parameter UART_BPS = 115200  ;    //���崮�ڲ�����//wire define
//wire         uart_rx_done;    //UART���������ź�
//wire  [7:0]  uart_rx_data;    //UART��������//*****************************************************
//**                    main code
//*****************************************************//���ڽ���ģ��
uart_rx #(.CLK_FREQ  (CLK_FREQ),.UART_BPS  (UART_BPS))    u_uart_rx(.clk           (sys_clk     ),.rst_n         (sys_rst_n   ),.uart_rxd      (uart_rxd    ),.uart_rx_done  (uart_rx_done),.uart_rx_data  (uart_rx_data));//���ڷ���ģ��
uart_tx #(.CLK_FREQ  (CLK_FREQ),.UART_BPS  (UART_BPS))    u_uart_tx(.clk          (sys_clk     ),.rst_n        (sys_rst_n   ),.uart_tx_en   (uart_tx_en),.uart_tx_data (uart_tx_data),.uart_tx_done (uart_tx_done),.uart_txd     (uart_txd    ),.uart_tx_busy (            ));endmodule
//****************************************Copyright (c)***********************************//
//ԭ�Ӹ����߽�ѧƽ̨��www.yuanzige.com
//����֧�֣�http://www.openedv.com/forum.php
//�Ա����̣�https://zhengdianyuanzi.tmall.com
//��ע΢�Ź���ƽ̨΢�źţ�"����ԭ��"�����ѻ�ȡZYNQ & FPGA & STM32 & LINUX���ϡ�
//��Ȩ���У�����ؾ���
//Copyright(C) ����ԭ�� 2023-2033
//All rights reserved                                  
//----------------------------------------------------------------------------------------
// File name:           uart_rx
// Created by:          ����ԭ��
// Created date:        2023��2��16��14:20:02
// Version:             V1.0
// Descriptions:        UART���ڽ���ģ��
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//module uart_rx(input               clk         ,  //ϵͳʱ��input               rst_n       ,  //ϵͳ��λ������Чinput               uart_rxd    ,  //UART���ն˿�output  reg         uart_rx_done,  //UART���������ź�output  reg  [7:0]  uart_rx_data  //UART���յ�������);//parameter define
parameter CLK_FREQ = 50000000;               //ϵͳʱ��Ƶ��
parameter UART_BPS = 115200  ;                 //���ڲ�����
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //Ϊ�õ�ָ�������ʣ���ϵͳʱ�Ӽ���BPS_CNT��//reg define
reg          uart_rxd_d0;
reg          uart_rxd_d1;
reg          uart_rxd_d2;
reg          rx_flag    ;  //���չ��̱�־�ź�
reg  [3:0 ]  rx_cnt     ;  //�������ݼ�����
reg  [15:0]  baud_cnt   ;  //�����ʼ�����
reg  [7:0 ]  rx_data_t  ;  //�������ݼĴ���//wire define
wire        start_en;//*****************************************************
//**                    main code
//*****************************************************
//�������ն˿��½���(��ʼλ)���õ�һ��ʱ�����ڵ������ź�
assign start_en = uart_rxd_d2 & (~uart_rxd_d1) & (~rx_flag);//�����첽�źŵ�ͬ������
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginuart_rxd_d0 <= 1'b0;uart_rxd_d1 <= 1'b0;uart_rxd_d2 <= 1'b0;endelse beginuart_rxd_d0 <= uart_rxd;uart_rxd_d1 <= uart_rxd_d0;uart_rxd_d2 <= uart_rxd_d1;end
end//�����ձ�־��ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) rx_flag <= 1'b0;else if(start_en)    //���⵽��ʼλrx_flag <= 1'b1; //���չ����У���־�ź�rx_flag���//��ֹͣλһ����ʱ�򣬼����չ��̽�������־�ź�rx_flag���else if((rx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX/2 - 1'b1))rx_flag <= 1'b0;elserx_flag <= rx_flag;
end        //�����ʵļ�������ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) baud_cnt <= 16'd0;else if(rx_flag) begin     //���ڽ��չ���ʱ�������ʼ�������baud_cnt������ѭ������if(baud_cnt < BAUD_CNT_MAX - 1'b1)baud_cnt <= baud_cnt + 16'b1;else baud_cnt <= 16'd0; //�����ﵽһ�����������ں�����end    elsebaud_cnt <= 16'd0;     //���չ��̽���ʱ����������
end//�Խ������ݼ�������rx_cnt�����и�ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) rx_cnt <= 4'd0;else if(rx_flag) begin                  //���ڽ��չ���ʱrx_cnt�Ž��м���if(baud_cnt == BAUD_CNT_MAX - 1'b1) //�������ʼ�����������һ������������ʱrx_cnt <= rx_cnt + 1'b1;        //�������ݼ�������1elserx_cnt <= rx_cnt;endelserx_cnt <= 4'd0;                     //���չ��̽���ʱ����������
end        //����rx_cnt��Ĵ�rxd�˿ڵ�����
always @(posedge clk or negedge rst_n) beginif(!rst_n) rx_data_t <= 8'b0;else if(rx_flag) begin                           //ϵͳ���ڽ��չ���ʱif(baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin  //�ж�baud_cnt�Ƿ�����������λ���м�case(rx_cnt)4'd1 : rx_data_t[0] <= uart_rxd_d2;   //�Ĵ����ݵ�����λ4'd2 : rx_data_t[1] <= uart_rxd_d2;4'd3 : rx_data_t[2] <= uart_rxd_d2;4'd4 : rx_data_t[3] <= uart_rxd_d2;4'd5 : rx_data_t[4] <= uart_rxd_d2;4'd6 : rx_data_t[5] <= uart_rxd_d2;4'd7 : rx_data_t[6] <= uart_rxd_d2;4'd8 : rx_data_t[7] <= uart_rxd_d2;   //�Ĵ����ݵĸߵ�λdefault : ;endcase  endelserx_data_t <= rx_data_t;endelserx_data_t <= 8'b0;
end        //�����������źźͽ��յ������ݸ�ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginuart_rx_done <= 1'b0;uart_rx_data <= 8'b0;end//���������ݼ�����������ֹͣλ����baud_cnt������ֹͣλ���м�ʱelse if(rx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX/2 - 1'b1) beginuart_rx_done <= 1'b1     ;  //��߽��������ź�uart_rx_data <= rx_data_t;  //����UART���յ������ݽ��и�ֵend    else beginuart_rx_done <= 1'b0;uart_rx_data <= uart_rx_data;end
endendmodule
//****************************************Copyright (c)***********************************//
//ԭ�Ӹ����߽�ѧƽ̨��www.yuanzige.com
//����֧�֣�http://www.openedv.com/forum.php
//�Ա����̣�https://zhengdianyuanzi.tmall.com
//��ע΢�Ź���ƽ̨΢�źţ�"����ԭ��"�����ѻ�ȡZYNQ & FPGA & STM32 & LINUX���ϡ�
//��Ȩ���У�����ؾ���
//Copyright(C) ����ԭ�� 2023-2033
//All rights reserved                                  
//----------------------------------------------------------------------------------------
// File name:           uart_tx
// Created by:          ����ԭ��
// Created date:        2023��2��16��14:20:02
// Version:             V1.0
// Descriptions:        UART���ڷ���ģ��
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//module uart_tx(input               clk         , //ϵͳʱ��input               rst_n       , //ϵͳ��λ������Чinput               uart_tx_en  , //UART�ķ���ʹ��input     [7:0]     uart_tx_data, //UARTҪ���͵�����output  reg         uart_txd    , //UART���Ͷ˿�output  reg  [3:0]  tx_cnt      ,  //�������ݼ�����output  reg  [15:0] baud_cnt    ,  //�����ʼ�����output  reg         uart_tx_done,output  reg         uart_tx_busy  //����æ״̬�ź�);//parameter define
parameter CLK_FREQ = 50000000;               //ϵͳʱ��Ƶ��
parameter UART_BPS = 115200  ;               //���ڲ�����
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //Ϊ�õ�ָ�������ʣ���ϵͳʱ�Ӽ���BPS_CNT��//reg define
reg  [7:0]  tx_data_t;  //�������ݼĴ���
//�����ʵļ�������ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) uart_tx_done<=1'b0;else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) beginuart_tx_done<=1'b1;end    elseuart_tx_done<=1'b0;     //���͹��̽���ʱ����������
end//*****************************************************
//**                    main code
//*****************************************************//��uart_tx_enΪ��ʱ���Ĵ������IJ������ݣ������BUSY�ź�
always @(posedge clk or negedge rst_n) beginif(!rst_n) begintx_data_t <= 8'b0;uart_tx_busy <= 1'b0;end//����ʹ��ʱ���Ĵ�Ҫ���͵����ݣ������BUSY�ź�else if(uart_tx_en) begintx_data_t <= uart_tx_data;uart_tx_busy <= 1'b1;end//��������ֹͣλ����ʱ��ֹͣ���͹���else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) begintx_data_t <= 8'b0;     //���շ������ݼĴ���uart_tx_busy <= 1'b0;  //�����BUSY�ź�endelse begintx_data_t <= tx_data_t;uart_tx_busy <= uart_tx_busy;end
end//�����ʵļ�������ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) baud_cnt <= 16'd0;else if(uart_tx_en)  baud_cnt <= 16'd0;      //�����ڷ��͹���ʱ�������ʼ�������baud_cnt������ѭ������else if(uart_tx_busy) beginif(baud_cnt < BAUD_CNT_MAX - 1'b1)baud_cnt <= baud_cnt + 16'b1;else baud_cnt <= 16'd0; //�����ﵽһ�����������ں�����end    elsebaud_cnt <= 16'd0;     //���͹��̽���ʱ����������
end//tx_cnt���и�ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) tx_cnt <= 4'd0;else if(uart_tx_en)  tx_cnt <= 16'd0;         else if(uart_tx_busy) begin             //���ڷ��͹���ʱtx_cnt�Ž��м���if(baud_cnt == BAUD_CNT_MAX - 1'b1) //�������ʼ�����������һ������������ʱtx_cnt <= tx_cnt + 1'b1;        //�������ݼ�������1elsetx_cnt <= tx_cnt;endelsetx_cnt <= 4'd0;                     //���͹��̽���ʱ����������
end//����tx_cnt���uart���Ͷ˿ڸ�ֵ
always @(posedge clk or negedge rst_n) beginif(!rst_n) uart_txd <= 1'b1;else if(uart_tx_busy) begincase(tx_cnt) 4'd0 : uart_txd <= 1'b0        ; //��ʼλ4'd1 : uart_txd <= tx_data_t[0]; //����λ����λ4'd2 : uart_txd <= tx_data_t[1];4'd3 : uart_txd <= tx_data_t[2];4'd4 : uart_txd <= tx_data_t[3];4'd5 : uart_txd <= tx_data_t[4];4'd6 : uart_txd <= tx_data_t[5];4'd7 : uart_txd <= tx_data_t[6];4'd8 : uart_txd <= tx_data_t[7]; //����λ����λ4'd9 : uart_txd <= 1'b1        ; //ֹͣλdefault : uart_txd <= 1'b1;endcaseendelseuart_txd <= 1'b1;                    //����ʱ���Ͷ˿�Ϊ�ߵ�ƽ
endendmodule

2.数码管驱动

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/05/03 20:43:29
// Design Name: 
// Module Name: seg_ctrl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module seg_ctrl( input				   clk		,input				   rst_n	,input		[23:0]	din		,input      [5:0]    point_n ,output	reg	[5:0]	sel	,output	reg	[7:0]	dig  
);								 parameter TIME_1MS = 50_000;//1mslocalparam NUM_0 = 7'b100_0000,//0NUM_1 = 7'b111_1001,//1NUM_2 = 7'b010_0100,//NUM_3 = 7'b011_0000,//NUM_4 = 7'b001_1001,//NUM_5 = 7'b001_0010,//NUM_6 = 7'b000_0010,//NUM_7 = 7'b111_1000,//NUM_8 = 7'b000_0000,//NUM_9 = 7'b001_0000,//A     = 7'b000_1000,//B     = 7'b000_0011,//bC     = 7'b100_0110,//OFF   = 7'b111_1111,//???CROSS = 7'b011_1111,//????//D     = 7'b010_0001,//d//E     = 7'b000_0110,//F     = 7'b000_1110;////---------<?????????>-----------------------------------------------------reg			[15:0]	cnt_1ms	   	;//1ms???????????????????????wire				add_cnt_1ms	;wire				end_cnt_1ms	;reg         [3:0]   disp_data   ;//??¦Ë??????????????reg                 point_n_r   ;//??¦Ë???????????§³????//****************************************************************
//--cnt_1ms
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_1ms <= 'd0;end else if(add_cnt_1ms)begin if(end_cnt_1ms)begin cnt_1ms <= 'd0;endelse begin cnt_1ms <= cnt_1ms + 1'b1;end endend assign add_cnt_1ms = 1'b1;//??????????assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;//****************************************************************
//--seg_sel
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginsel <= 6'b111_110;//?????¦Ë???????????¦Ë??????end else if(end_cnt_1ms)begin sel <= {sel[4:0],sel[5]};//???????end end//****************************************************************
//--disp_data
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begindisp_data <= 'd0;point_n_r <= 1'b1;end else begin case (sel)6'b111_110 : begin disp_data <= din[3:0]  ; point_n_r <= point_n[0]; end//???¦Ë??????????????6'b111_101 : begin disp_data <= din[7:4]  ; point_n_r <= point_n[1]; end6'b111_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end6'b110_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end6'b101_111 : begin disp_data <= din[19:16]; point_n_r <= point_n[4]; end6'b011_111 : begin disp_data <= din[23:20]; point_n_r <= point_n[5]; enddefault: disp_data <= 'd0;endcaseend end//****************************************************************
//--seg_dig
//****************************************************************always @(*)begin case (disp_data)0 :  dig = {point_n_r,NUM_0};1 :  dig = {point_n_r,NUM_1};2 :  dig = {point_n_r,NUM_2};3 :  dig = {point_n_r,NUM_3};4 :  dig = {point_n_r,NUM_4};5 :  dig = {point_n_r,NUM_5};6 :  dig = {point_n_r,NUM_6};7 :  dig = {point_n_r,NUM_7};8 :  dig = {point_n_r,NUM_8};9 :  dig = {point_n_r,NUM_9};10 : dig = {point_n_r,A    };11 : dig = {point_n_r,B    };12 : dig = {point_n_r,C    };13 : dig = {point_n_r,CROSS};14 : dig = {point_n_r,OFF  };15 : dig = {point_n_r,F    };default: dig = 8'hff;endcaseendendmodule

3.顶层模块

module top(input                     sys_clk  ,  input                     rst_n, input            		   uart_rxd ,   output           		   uart_txd ,output				wire		beep,output wire [5:0]	      sel	,output wire [7:0]	      dig   ,// UART相关信号output wire         uart_tx_en,output wire         uart_rx_done,output wire         uart_tx_done,output wire [7:0]   uart_tx_data,output wire [7:0]   uart_rx_data,// FIFO相关信号 output wire         rd_en,output wire         wr_en,output wire         empty,output wire         full,output reg          rd_en_reg,output wire [7:0]   q,output wire [23:0]	seg_data,output wire [6:0]   data_count);parameter TIME_250MS =   24'd12500000;
uart
//wire            uart_tx_en; 
//wire            uart_rx_done; 
//wire            uart_tx_done; 
//wire  [7:0]     uart_tx_data; 
//wire  [7:0]     uart_rx_data; fifo
//wire empty;
//wire full;
//wire [7:0]  q;
//wire [6:0]  data_count;
reg	[23:0]	cnt;assign rd_en=(cnt==TIME_250MS && ~empty)?1'b1:1'b0;
assign wr_en=(data_count<7'd100)? uart_rx_done : 1'b0;always @(posedge sys_clk or negedge rst_n) beginif(!rst_n) begincnt<=24'd0;endelse if(cnt<TIME_250MS)begincnt<=cnt+1;endelse begincnt<=24'd0;end
endalways @(posedge sys_clk or negedge rst_n) beginif(!rst_n) beginrd_en_reg<=1'b0;endelse beginrd_en_reg<=rd_en;end
enduart_top u_uart_top(.sys_clk(sys_clk)  ,   .sys_rst_n(rst_n),   .uart_rx_done  (uart_rx_done),.uart_rx_data  (uart_rx_data),.uart_tx_en   (uart_tx_en),.uart_tx_data (uart_tx_data),.uart_tx_done (uart_tx_done),.uart_rxd(uart_rxd) ,  .uart_txd(uart_txd)    );fifo	fifo_inst (.clock ( sys_clk ),.data  ( uart_rx_data ),.rdreq ( rd_en ),.wrreq ( wr_en),.empty ( empty ),.full  ( full ),.q ( q ),.usedw ( data_count ));beep_uart u_beep_uart(.sys_clk    (sys_clk),.sys_rst_n  (rst_n),.beep_start (rd_en_reg),.uart_data  (q),.beep       (beep)
);display_data u_display_data(.sys_clk    (sys_clk),.sys_rst_n  (rst_n),.move_start (rd_en_reg),.uart_data  (q),.seg_data   (seg_data)
);seg_ctrl u_seg_ctrl(.clk     (sys_clk),         // 系统时钟.rst_n   (rst_n),       // 系统复位.din     (seg_data),   // 显示数据输入.point_n (6'b111111),   // 小数点选择.sel     (sel),     // 位选输出.dig     (dig)      // 段选输出
);endmodule

4.蜂鸣器驱动

module  beep_uart
(input   wire        sys_clk     ,   //系统时钟,频率50MHzinput   wire        sys_rst_n   ,   //系统复位,低有效input	wire			beep_start  ,input	wire	[7:0] uart_data   ,output  reg         beep            //输出蜂鸣器控制信号
);//后台私信获取endmodule

相关文章:

  • Franka 机器人在配置空间距离场实验中的突破性应用:从算法优化到动态场景适配
  • Stable Diffusion 3终极提示词库:2000个工业设计场景生成公式(2025企业级实战指南)
  • html css js网页制作成品——HTML+CSS湘菜网页设计(4页)附源码
  • Ehcache、Caffeine、Spring Cache、Redis、J2Cache、Memcached 和 Guava Cache 的主要区别
  • 自动化保护 AWS ECS Fargate 服务:使用 Prisma Cloud 实现容器安全
  • 无人机防护装置技术解析
  • 5,FreeRTOS中断管理
  • 本地部署 WordPress 博客完整指南(基于 XAMPP)
  • 替代创维GL3213S 读卡DD3118方案3.0国产 GL3224-32 TF/SD卡解码芯片
  • 【开源项目】「安卓原生3D开源渲染引擎」:Sceneform‑EQR
  • 汽车涂胶车间的“通信桥梁”:PROFIBUS DP转ETHERNET/IP网关的应用实践
  • 高防IP在服务器中的作用都有哪些?
  • 微信小程序进度条progress支持渐变色
  • iOS 网络请求断连重试失败?抓包分析丢包原因的完整流程
  • 设计模式精讲 Day 15:解释器模式(Interpreter Pattern)
  • .net8创建tcp服务接收数据通过websocket广播
  • 安科瑞碳计量电表与碳资产管理平台:企业双碳转型的智能中枢
  • Kamailio SIP+RTP双网卡SBC呼叫流程与媒体处理说明
  • Flutter 网络栈入门,Dio 与 Retrofit 全面指南
  • <script setup> 语法糖