已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
DE2实践之WM8731产生正弦波经历近三周的时间,终于搞定了wm8731产生1khz正弦波的那个DEMO。现在就将这三周来的收获做一个记录,希望大家与我共同分享,共同进步。 一.本DEMO 的目的 通过fpga控制音频编解码芯片wm8731产生一个1khz的正弦波,接上de2板上的耳机接口,试听此正弦波。 二.原理FPGA与wm8731共有5个接口,分别为SCLK,SDIN,DACLRC,DACDAT,BCLK.其中SCLK,SDIN为控制接口,DACLRC,DACDAT,BCLK为数字音频接口。由SCLK,SDIN配置wm8731的寄存器,由DACLRC,DACDAT,BCLK产生所需的正弦波并输出到耳机接口。详细原理见代码中注释。代码如下1. sclk,sdin数据传输时序代码(i2c写控制代码)module i2c_com(clock_i2c, /wm8731控制接口传输所需时钟,0-400khz,此处为20khz reset_n, ack, /应答信号 i2c_data, /sdin接口传输的24位数据 start, /开始传输标志 tr_end, /传输结束标志 cyc_count, i2c_sclk, /FPGA与wm8731时钟接口 i2c_sdat); /FPGA与wm8731数据接口 input 23:0i2c_data; input reset_n; input clock_i2c; output 5:0cyc_count; output ack; input start; output tr_end; output i2c_sclk; inout i2c_sdat; reg 5:0 cyc_count; reg reg_sdat; reg sclk; reg ack1,ack2,ack3; reg tr_end; wire i2c_sclk; wire i2c_sdat; wire ack; assign ack=ack1|ack2|ack3; assign i2c_sclk=sclk|(cyc_count=4)&(cyc_count=30)?clock_i2c:0); assign i2c_sdat=reg_sdat?1bz:0; always(posedge clock_i2c or negedge reset_n) begin if(!reset_n) cyc_count=6b111111; else begin if(start=0) cyc_count=0; else if(cyc_count6b111111) cyc_count=cyc_count+1; end end always(posedge clock_i2c or negedge reset_n) begin if(!reset_n) begin tr_end=0; ack1=1; ack2=1; ack3=1; sclk=1; reg_sdat=1; end else case(cyc_count) 0:begin ack1=1;ack2=1;ack3=1;tr_end=0;sclk=1;reg_sdat=1;end 1:reg_sdat=0; /开始传输 2:sclk=0; 3:reg_sdat=i2c_data23; 4:reg_sdat=i2c_data22; 5:reg_sdat=i2c_data21; 6:reg_sdat=i2c_data20; 7:reg_sdat=i2c_data19; 8:reg_sdat=i2c_data18; 9:reg_sdat=i2c_data17; 10:reg_sdat=i2c_data16; 11:reg_sdat=1; /应答信号 12:begin reg_sdat=i2c_data15;ack1=i2c_sdat;end 13:reg_sdat=i2c_data14; 14:reg_sdat=i2c_data13; 15:reg_sdat=i2c_data12; 16:reg_sdat=i2c_data11; 17:reg_sdat=i2c_data10; 18:reg_sdat=i2c_data9; 19:reg_sdat=i2c_data8; 20:reg_sdat=1; /应答信号 21:begin reg_sdat=i2c_data7;ack2=i2c_sdat;end 22:reg_sdat=i2c_data6; 23:reg_sdat=i2c_data5; 24:reg_sdat=i2c_data4; 25:reg_sdat=i2c_data3; 26:reg_sdat=i2c_data2; 27:reg_sdat=i2c_data1; 28:reg_sdat=i2c_data0; 29:reg_sdat=1; /应答信号 30:begin ack3=i2c_sdat;sclk=0;reg_sdat=0;end 31:sclk=1; 32:begin reg_sdat=1;tr_end=1;end endcase endendmodule这里需要关键注意的是i2c的写控制时序要把握准确:个人总结如下图: 说明:A:这里的i2c控制器采用33个i2c时钟周期进行,其中3-10,12-19,21-28传送数据,11,20,29为应答位。B:空闲状态时,sdat为高阻态,sclk为高电平状态。C:每发送1个字节的数据,就应返回一个应答信号将sdat状态拉低。D:实际传输时,24位的数据各部分为下:a 第1个字节的前7位为wm8731器件地址,第8位为读或写选择位,写为0,读为1.b 第2个字节的前7位为wm8731中寄存器的地址位,第8位为寄存器中9位数据的最高位。c 第3个字节的8位数据为wm8731中寄存器中9位数据的低8位。 2. wm8731中寄存器的配置程序 module reg_config(clock_50m, i2c_sclk, i2c_sdat, reset_n); input clock_50m; input reset_n; output i2c_sclk; inout i2c_sdat; reg clock_20k; reg 15:0clock_20k_cnt; reg 1:0config_step; reg 3:0reg_index; reg 23:0i2c_data; reg 15:0reg_data; reg start; i2c_com u1(.clock_i2c(clock_20k), .reset_n(reset_n), .ack(ack), .i2c_data(i2c_data), .start(start), .tr_end(tr_end), .i2c_sclk(i2c_sclk), .i2c_sdat(i2c_sdat); always(posedge clock_50m or negedge reset_n) /产生i2c控制时钟-20khz begin if(!reset_n) begin clock_20k=0; clock_20k_cnt=0; end else if(clock_20k_cnt2499) clock_20k_cnt=clock_20k_cnt+1; else begin clock_20k=!clock_20k; clock_20k_cnt=0; end end always(posedge clock_20k or negedge reset_n) /配置过程控制 begin if(!reset_n) begin config_step=0; start=0; reg_index=0; end else begin if(reg_index10) begin case(config_step) 0:begin i2c_data=8h34,reg_data; start=1; config_step=1; end 1:begin if(tr_end) begin if(!ack) config_step=2; else config_step=0; start=0; end end 2:begin reg_index=reg_index+1; config_step=0; end endcase end end end always(reg_index) begin case(reg_index) 0:reg_data=16h001f; 1:reg_data=16h021f; 2:reg_data=16h047f; 3:reg_data=16h067f; 4:reg_data=16h08f8; 5:reg_data=16h0a06; 6:reg_data=16h0c00; 7:reg_data=16h0e01; 8:reg_data=16h1002; 9:reg_data=16h1201; default:reg_data=16h001a; endcase endendmodule 关于此段代码的解释:A:此处实例化了前面提到的i2c控制的程序。B:共对wm8731中的10个寄存器进行配置,详细的寄存器信息与每位数据的表示意义参考wm8731的datasheet。C:wm8731允许的i2c控制时钟在0-400khz有效,这里应用20khz。D:配置过程控制这段代码很关键,尤其要注意开始和结束信号的控制3.正弦波产生程序 module sinwave_gen(clock_ref,dacclk,bclk,dacdat,reset_n);input clock_ref; /wm8731输入时钟,18.432Mhz; input reset_n; output dacclk; output dacdat; output bclk; reg dacclk; reg 8:0dacclk_cnt; reg bclk; reg 3:0bclk_cnt; reg 3:0data_num; reg 15:0sin_out; reg 5:0sin_index; parameter CLOCK_REF=18432000; parameter CLOCK_SAMPLE=48000; always(posedge clock_ref or negedge reset_n) /生产正弦波采样时钟48khz begin if(!reset_n) begin dacclk=0; dacclk_cnt=(CLOCK_REF/(CLOCK_SAMPLE*2)-1) begin dacclk=dacclk; dacclk_cnt=0; end else dacclk_cnt=dacclk_cnt+1; end always(posedge clock_ref or negedge reset_n) /生产16位数据传输时钟,正弦波采样时钟的32倍 begin if(!reset_n) begin bclk=0; bclk_cnt=(CLOCK_REF/(CLOCK_SAMPLE*2*16*2)-1) begin bclk=bclk; bclk_cnt=0; end else bclk_cnt=bclk_cnt+1; end always(negedge bclk or negedge reset_n) begin if(!reset_n) data_num=0; else data_num=data_num+1; end always(negedge dacclk or negedge reset_n) begin if(!reset_n) sin_index=0; else if(sin_index47) sin_index=sin_index+1; else sin_index=0; end assign dacdat=sin_outdata_num; /产生DA转换器数字音频数据 always(sin_index) begin case(sin_index) 0 : sin_out = 0 ; /32767*sin0 1 : sin_out = 4276 ; /32767*sin7.5(角度) 2 : sin_out = 8480 ; /32767*sin15(角度) 3 : sin_out = 12539 ; 4 : sin_out = 16383 ; 5 : sin_out = 19947 ; 6 : sin_out = 23169 ; 7 : sin_out = 25995 ; 8 : sin_out = 28377 ; 9 : sin_out = 30272 ; 10 : sin_out = 31650 ; 11 : sin_out = 32486 ; 12 : sin_out = 32767 ; 13 : sin_out = 32486 ; 14 : sin_out = 31650 ; 15 : sin_out = 30272 ; 16 : sin_out = 28377 ; 17 : sin_out = 25995 ; 18 : sin_out = 23169 ; 19 : sin_out = 19947 ; 20 : sin_out = 16383 ; 21 : sin_out = 12539 ; 22 : sin_out = 8480 ; 23 : sin_out = 4276 ; 24 : sin_out = 0 ; 25 : sin_out = 61259 ; 26 : sin_out = 57056 ; 27 : sin_out = 52997 ; 28 : sin_out = 49153 ; 29 : sin_out = 45589 ; 30 : sin_out = 42366 ; 31 : sin_out = 39540 ; 32 : sin_out = 37159 ; 33 : sin_out = 35263 ; 34 : sin_out = 33885 ; 35 : sin_out = 33049 ; 36 : sin_out = 32768 ; 37 : sin_out = 33049 ; 38 : sin_out = 33885 ; 39 : sin_out = 35263 ; 40 : sin_out = 37159 ; 41 : sin_out = 39540 ; 42 : sin_out = 42366 ; 43 : sin_out = 45589 ; 44 : sin_out = 49152 ; 45 : sin_out = 52997 ; 46 : sin_out = 57056 ; 47 : sin_out = 61259 ; endcase endendmodule关于此段代码的解释:由于采样速率是48khz,在所要产生的正弦波的一个周期内进行了48此采样,所以得到的正弦波的频率是1khz。 4.wm8731的输入时钟要求为18.432Mhz,此时钟由DE2板上27Mhz晶振由altera的PLL分频得到。由于27Mhz不能精确地分频到18.432Mhz,所以采用了一个能分到一个最接近的频率,即18.409091Mhz。分频程序如下: module audio_pll ( inclk0, c0); input inclk0; output c0; wire 5:0 sub_wire0; wire 0:0 sub_wire4 = 1h0; wire 0:0 sub_wire1 = sub_wire00:0; wire c0 = sub_wire1; wire sub_wire2 = inclk0; wire 1:0 sub_wire3 = sub_wire4, sub_wire2; altpll altpll_component ( .inclk (sub_wire3), .clk (sub_wire0), .activeclock (), .areset (1b0), .clkbad (), .clkena (61b1), .clkloss (), .clkswitch (1b0), .configupdate (1b0), .enable0 (), .enable1 (), .extclk (), .extclkena (41b1), .fbin (1b1), .fbmimicbidir (), .fbout (), .locked (), .pfdena (1b1), .phasecounterselect (41b1), .phasedone (), .phasestep (1b1), .phaseupdown (1b1), .pllena (1b1), .scanaclr (1b0), .scanclk (1b0), .scanclkena (1b1), .scandata (1b0), .scandataout (), .scandone (), .scanread (1b0), .scanwrite (1b0), .sclkout0 (), .sclkout1 (), .vcooverrange (), .vcounderrange (); defparam altpll_component.clk0_divide_by = 27000000, altpll_component.clk0_duty_cycle = 50, altpll_component.clk0_multiply_by = 18409091, altpll_component.clk0_phase_shift = 0, altpll_pensate_clock = CLK0, altpll_component.inclk0_input_frequency = 37037, altpll_ended_device_family = Cyclone II, altpll_component.lpm_hint = CBX_MODULE_PREFIX=Audio_PLL, altpll_component.lpm_type = altpll, altpll_component.operation_mode = NORMAL, altpll_component.port_activeclock = PORT_UNUSED, altpll_component.port_areset = PORT_UNUSED, altpll_component.port_clkbad0 = PORT_UNUSED, altpll_component.port_clkbad1 = PORT_UNUSED, altpll_component.port_clkloss = PORT_UNUSED, altpll_component.port_clkswitch = PORT_UNUSED, altpll_component.port_configupdate = PORT_UNUSED, altpll_component.port_fbin = PORT_UNUSED, altpll_component.port_inclk0 = PORT_USED, altpll_component.port_inclk1 = PORT_UNUSED, altpll_component.port_locked = PORT_UNUSED, altpll_component.port_pfdena = PORT_UNUSED, altpll_component.port_phasecounterselect = PORT_UNUSED, altpll_component.port_phasedone = PORT_UNUSED, altpll_component.port_phasestep = PORT_UNUSED, altpll_component.port_phaseupdown = PORT_UNUSED, altpll_component.port_pllena = PORT_UNUSED, altpll_component.port_scanaclr = PORT_UNUSED, altpll_component.port_scanclk = PORT_UNUSED, altpll_component.port_scanclkena = PORT_UNUSED, altpll_component.port_scandata = PORT_UNUSED, altpll_component.port_scandataout = PORT_UNUSED, altpll_component.port_scandone = PORT_UNUSED, altpll_component.port_scanread = PORT_UNUSED, altpll_component.port_scanwrite = PORT_U
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 内蒙古呼伦贝尔市2025年生物高二上期末调研模拟试题含解析
- 上海市进才实验中学2026届化学高二上期末考试模拟试题含解析
- 阜阳师范大学信息工程学院《语言基础知识教学论》2024-2025学年第一学期期末试卷
- 法律服务的市场分析
- 小区物业保洁主管目标责任书
- 北京工业大学本科生毕业设计(论文)撰写规范-2025
- 电力行业存在的困难及其解决对策
- 新版全国计算机等级考试二级MSoffice选择题题库
- 硕士研究生毕业论文开题报告写作技巧及范文
- 【毕业论文】物流管理专业毕业论文连锁超市配送线路优化研究
- 2025年消防安全知识答题库(附答案)
- 喷漆外包管理办法
- 稽留流产的课件
- 租车挂靠协议书
- 人民医院改扩建建设项目水土保持方案
- 绿色插画风小蝌蚪找妈妈绘本故事
- 官兵心理健康教育
- 公务员职业生涯发展课件
- GB/T 192-2025普通螺纹牙型
- CRRT授权管理制度
- 2025-2030中国电缆敷设船行业市场发展趋势与前景展望战略研究报告
评论
0/150
提交评论