数字系统设计音乐播放器文档格式.docx

上传人:b****5 文档编号:17467259 上传时间:2022-12-01 格式:DOCX 页数:20 大小:391.14KB
下载 相关 举报
数字系统设计音乐播放器文档格式.docx_第1页
第1页 / 共20页
数字系统设计音乐播放器文档格式.docx_第2页
第2页 / 共20页
数字系统设计音乐播放器文档格式.docx_第3页
第3页 / 共20页
数字系统设计音乐播放器文档格式.docx_第4页
第4页 / 共20页
数字系统设计音乐播放器文档格式.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

数字系统设计音乐播放器文档格式.docx

《数字系统设计音乐播放器文档格式.docx》由会员分享,可在线阅读,更多相关《数字系统设计音乐播放器文档格式.docx(20页珍藏版)》请在冰豆网上搜索。

数字系统设计音乐播放器文档格式.docx

Input

100MHz时钟信号

reset

复位信号,高电平有效

play_button

“播放”按键,低电平有效

next_button

“下一曲”按键,一个时钟周期宽度的高电平脉冲

play

Output

高电平表示播放

song_done

当播放下一曲时,输出一个时钟周期宽度的高电平复位脉冲reset_play,并复位note_player模块

note_player模块的应答信号一个时钟周期宽度的高电平脉冲表示一曲播放结束

song[1:

0]

当前乐曲的序号

结合以上算法流程图和端口定义,mcu模块代码如下:

modulemcu(clk,reset,play_button,next,play,reset_play,song,song_done);

parameterRESET=0,WAIT=1,END=2,NEXT=3,PLAY=4;

inputreset,play_button,song_done,clk,next;

outputreg[1:

0]song;

outputregplay,reset_play;

regstate;

always@(posedgeclk)

begin

if(reset)

beginplay<

=0;

song<

=2'

b00;

reset_play<

=1;

state<

=RESET;

end

else

case(state)

RESET:

beginreset_play<

=WAIT;

WAIT:

if(song_done)

beginstate<

=END;

play<

reset_play<

elseif(next)

beginstate<

=NEXT;

=song+1;

elseif(~play_button)

=PLAY;

END,NEXT,PLAY:

endcase

end

endmodule

2、乐曲读取模块song_reader的设计

乐曲读取模块song_reader的功能有:

(1)根据mcu模块的要求,选择播放乐曲;

(2)相应note_player模块请求,从song_rom中逐个取出音符{note,duration}送给note_player模块播放;

(3)判断乐曲是否播放完毕,若播放完毕,则回复mcu模块应答信号。

 

根据设计要求,以下是song_reader模块的结构框图

根据设计要求,以下是song_reader模块的端口含义

100MH时钟信号

来自mcu的控制信号,高电平播放

来自mcu的控制信号,当前播放乐曲的序号

note_done

来自模块note_player应答信号,一个时钟周期宽度的高电平脉冲表示一个音符播放结束

0utput

给mcu的应答信号,当乐曲播放结束,输出一个时钟周期宽度的高电平脉冲

note[5:

音符标记

duration[5:

音符的持续时间

new_note

给note_player的控制信号,一个时钟周期宽度的高电平脉冲表示新的音符需播放

以下是song_reader的算法流程图

地址计数器为5位二进制计数器,其中note_done为计数允许输入,状态q为song_rom的低5位地址,song[1:

0]为song_rom高两位地址。

当地址计数器出现进位或duration为0时,表示乐曲结束,应输出一个时钟周期宽度的高电平脉冲信号song_done。

结束判断模块应调用提供的模块one_pulse,使输出为一个时钟周期宽度的高电平脉冲。

结合上图以及模块要求,编写song_reader代码如下:

modulesong_reader(clk,reset,play,song,note_done,song_done,note,duration,new_note);

inputclk,reset,play,note_done;

input[1:

outputsong_done,new_note;

output[5:

0]note,duration;

parameterRESET=0,NEW_NOTE=1,WAIT=2,NEXT_NOTE=4;

reg[1:

0]STATE;

regnew_note;

always@(posedgeclk)

begin

if(reset==1)beginnew_note<

STATE<

case(STATE)

RESET:

if(play==1)

beginnew_note<

=NEW_NOTE;

else

NEW_NOTE:

if(play==1)

if(note_done==1)

beginnew_note<

=NEXT_NOTE;

else

beginnew_note<

elsebeginnew_note<

NEXT_NOTE:

endcase

wire[4:

0]q;

wireco;

song_romsong_rom1(.clk(clk),.dout({note,duration}),.addr({song,q}));

addr_counteraddr_counter1(.clk(clk),.reset(reset),.note_done(note_done),.q(q),.co(co));

end_judgingend_judging1(.co(co),.duration(duration),.clk(clk),.song_done(song_done));

(返回给主控制器一个应答信号,即框图中的结束判断模块)

其中模块end_judging的代码如下:

moduleend_judging(co,duration,clk,song_done);

parameterN=6;

inputco;

input[N-1:

0]duration;

inputclk;

outputsong_done;

wire[N-1:

0]dd;

wireqq;

assignsong_done=~qq&

dd;

assigndd=co|(duration==6'

b00000);

D_FFdff1(.d(dd),.clk(clk),.q(qq));

其中模块counter的代码如下:

moduleaddr_counter(clk,q,co,reset,note_done);

inputclk,reset,note_done;

outputreg[4:

outputco;

assignco=note_done&

&

(&

q);

always@(posedgeclk)

begin

if(reset)beginq<

else

beginif(note_done)q<

=q+1;

q<

=q;

end

endmodule

3、音符播放模块note_player的设计

音符播放模块note_player是本实验的核心模块,它的主要功能有:

(1)从送song_reader模块接收所需播放的音符信息{note,duration};

(2)根据note值找出DDS的相位增量step_size;

(3)以48kHz速率从SineROM取出正弦样品送给AC97接口模块;

(4)当一个音符播放完毕,向song_reader模块索取新的音符。

根据note_player模块的任务,进一步划分功能单元,为简化设计,可将产生正弦样品的DDS模块设计一个独立子模块sine_reader。

note_player控制器负责与song_reader模块接口,读取音符信息,并根据音符信息从FrequencyROM中读取相位增量step_size送给DDS子模块sine_reader。

另外,note_player控制器还需要控制音符播放时间。

note_player控制器的算法流程如下。

在复位或未播放时,控制器处于RESET状态,PLAY为音符播放状态,当一个音符播放结束时,控制器进入DONE状态,PLAY为音符播放状态,当一个音符播放结束时,控制器进入DONE状态,置位done_with_note,向song_reader模块索取新的音符,然后进入LOAD状态,读取新的音符后进入PLAY状态播放下一个音符。

note_player模块的结构框图如下:

note_player控制器的算法流程图如下:

音符定时器为6位二进制计数器,beat、time_clear分别为使能、清0信号,均为高电平有效。

定时时间为音符的长短(duration_to_load个beat周期),timer_done为定时结束标志。

根据实验要求以下是note_player模块代码:

modulenote_player(clk,reset,play_enable,note_to_load,duration_to_load,

done_with_note,load_new_note,beat,generate_next_sample,sample_out,new_sample_ready);

inputclk;

inputreset;

//Whenhighweplay,whenlowwedon'

t.

inputplay_enable;

//Thenotetoplay

input[5:

0]note_to_load;

//Thedurationofthenotetoplay

0]duration_to_load;

//Tellsuswhenwehaveanewnotetoload

inputload_new_note;

//Whenwearedonewiththenotethisstayshigh.

outputdone_with_note;

//regdone_with_note;

//Thisisour1/48thsecondbeat

inputbeat;

//Tellsuswhenthecodecwantsanewsample

inputgenerate_next_sample;

//Oursampleoutput

output[15:

0]sample_out;

//Tellsthecodecwhenwe'

vegotasample

outputnew_sample_ready;

wire[19:

0]step_size;

sine_readersine_reader_inst(.clk(clk),.reset(reset),.step_size({10'

d18,10'

d791}),

.step_size(step_size),.generate_next_sample(generate_next_sample),

.new_sample_ready(new_sample_ready),.sample_out(sample_out));

(note_player控制器一段式描述代码)

parameterRESET=0,PLAY=1,LOAD=2,DONE=3;

reg[1:

0]state;

regdone_with_note;

regtimer_clear;

wiretimer_done;

reg[5:

0]note;

always@(posedgeclk)

if(reset)beginstate<

note<

=6'

b0;

done_with_note<

timer_clear<

case(state)

RESET,LOAD,DONE:

if(~play_enable)beginstate<

end

elseif(~load_new_note)

beginstate<

end

else

beginstate<

=LOAD;

=note_to_load;

end

PLAY:

if(timer_done)

beginstate<

=DONE;

end

elseif(~play_enable)

elseif(~load_new_note)

state<

elsebeginstate<

timer_clear<

default:

beginstate<

end

endcase

frequency_romfrequency_rom_inst(.clk(clk),.dout(step_size),.addr(note));

note_timernote_timer(.cin(duration_to_load),.en(beat),

.clk(clk),.r(timer_clear),.cout(timer_done));

其中模块note_timer音符定时器代码如下:

modulenote_timer(cout,cin,r,clk,en);

parametern=6;

reg[n-1:

outputcout;

input[n-1:

0]cin;

inputr,clk,en;

assigncout=en&

(q==(cin-1));

always@(posedgeclk)

if(r)q=0;

elseif(en)q=q+1;

elseq=q;

子模块sine_reader的功能就是利用DDS技术产生正弦样品。

在本实验中,系统时钟clk与取样脉冲generate_next_sample为两个不同信号;

实验中相位增量为22位,其中小数部分为10位。

对于step_size本身为20位二进制数的问题,可通过对其进行{2’b00,step_size}处理使其扩展至22位。

sine_reader原理框图:

sine_rom的地址和数据处理方法:

区域(raw_addr[21:

20])

SineRom地址(rom_addr)

Sample

00

raw_addr[19:

10]

raw_data[15:

01

当raw_addr[20:

10]=1024时,rom_addr取1023;

其余取~raw_addr[19:

10]+1

10

~raw_data[15:

0]+1

11

由以上sine_reader原理框图以及sine_rom的地址和数据处理方法可得sine_reader模块代码。

modulesine_reader(step_size,clk,generate_next_sample,reset,sample_out,new_sample_ready);

input[19:

inputclk,generate_next_sample,reset;

wire[21:

0]raw_addr;

0]sum;

wire[9:

0]rom_addr;

wire[15:

0]sample;

0]raw_data;

full_adder#(22)

adder(.a(raw_addr),.b({2'

b00,step_size}),.s(sum),.ci(1'

b0),.co());

D_FFRE#(22)

dffr1(.d(sum),.en(generate_next_sample),.r(reset),.clk(clk),.q(raw_addr));

addr_processor

addr_pro(.in_addr(raw_addr[20:

10]),.out_addr(rom_addr));

sine_rom

sine_rom1(.clk(clk),.dout(raw_data),.addr(rom_addr));

data_processor#(16)

data_pro(.flag(raw_addr[21]),.in_data(raw_data),.out_data(sample));

D_FFRE#(16)dffr2(.d(sample),.en(generate_next_sample),.r(reset),.clk(clk),.q(sample_out));

D_FF

dffr3(.d(generate_next_sample),.clk(clk),.q(new_sample_ready));

其中地址处理(addr_processor)模块的代码如下:

moduleaddr_processor(in_addr

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 高中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1