首页 / 资讯中心 / 文章详情

Quartus原理图设计电子琴:分频消抖与板级联调

Quartus原理图设计电子琴:分频消抖与板级联调 ★ FEATURED ARTICLE
简介围绕Quartus II原理图设计方法展开的电子琴FPGA工程面向具备数字电路基础、希望以图形化方式入门FPGA开发的学生与爱好者。设计把音符频率生成、定时计数、DA转换接口、按键控制与乐曲存储拆成可逐级连接的模块频率部分可用查找表保存音高对应值计数器控制音符时值控制器响应按键存储模块保存乐曲序列便于理解从时钟分频到音频输出的链路。压缩包共413个文件约5.42MB以bdf原理图、bsf模块符号、vwf仿真波形、qsf/qpf工程配置、sof下载比特流和mif存储器初始化文件为主另含VHDL补充源码、编译报告与引脚分配等保留了较完整的Quartus工程目录与编译痕迹。已有1045人学习适合课程设计、实验复现与自学参考可按模块对照原理图、复现编译与下载流程并借编译报告和仿真波形排查时序、音准与引脚分配问题。1. 一块实验板上的电子琴Quartus 原理图设计到底交付了什么很多人第一次看到“Quartus 原理图设计方法设计的电子琴程序”会以为它只是一张画好连线的玩具图真正值得拿的是把系统时钟、按键消抖、音符频率表、音频输出和引脚约束串成一条可编译链路的工程骨架。电子琴这个题目小但边界很清楚时钟频率填错音准立刻偏蜂鸣器类型选错编译全过也不响按键不消抖弹起来像接触不良。它适合刚接触 Quartus 原理图输入、想把“能画图”推进到“能下载出声”的人也适合拿它当数字逻辑综合练习的熟手。2. 从空白工程到可编译顶层Quartus 原理图工程的搭建顺序原理图输入在 Quartus 里不是“画完就能编译”。工程参数、顶层实体名、子图符号和总线命名只要有一处对不上后面就会出现“图看起来没错编译却找不到实体”的情况。电子琴规模不大常见做法是用层次化原理图顶层只负责连线和端口分频、按键、音符查找、发声输出各自做成子图再生成符号给顶层调用。这样改一个音符表不用动整张图仿真时也能单独把分频器拎出来看波形。选型上要先定三件事目标器件按实验板手册来不要贪大系统时钟按板卡晶振填常见是 50 MHz但必须实测或查手册确认输出接口先分清是蜂鸣器、音频座还是数码管。原理图方式适合这种组合逻辑多、时序不深的小系统但图面一多就容易乱所以从第一张图开始就要按层次拆不要把所有计数器堆在顶层。2.1 器件与工程参数先定时钟、复位和输出接口新建工程时工程目录用英文路径不要带空格和中文。顶层实体名与顶层原理图文件名保持一致例如顶层图叫organ_top.bdf顶层实体就用organ_top。目标器件按实验板填写不要随手选一个同系列但引脚数不同的器件否则后面引脚分配会全部对不上。仿真工具格式按工程习惯设置功能仿真和时序仿真分开做先保证逻辑对再看延时。可执行顺序可以照下面走建独立工程目录把原理图、符号、初始化文件放在同一层或固定子目录。新建 Quartus 工程器件型号、封装、速度等级按板卡手册填。新建顶层原理图organ_top.bdf先只放输入输出端口。在工程设置里确认顶层实体名不要等编译报错再回头改。把系统时钟频率记在工程说明里分频参数全部按这个值算。先编译一次空顶层确认工程能过分析综合再往里加子图。信号方向作用参数注意clk_50m输入系统时钟必须接板载晶振频率与分频表一致rst_n输入复位确认按键极性低有效还是高有效key[7:0]输入琴键先做两级同步再做消抖beep输出蜂鸣器驱动无源蜂鸣器给方波有源蜂鸣器不能演奏seg[7:0]输出数码管段选共阴共阳要与板卡匹配dig[3:0]输出数码管位选注意驱动电流和扫描频率这张表不是让你照抄引脚而是先把接口方向定死。很多翻车不是逻辑错而是把输出口接到了输入按键上或者把时钟接到了普通 IO。时钟尽量走板卡标注的专用时钟引脚复位和按键走普通 IO 没问题但按键输入一定要做同步处理。2.2 顶层原理图与符号复用把分频、按键、发声拆成可连线模块层次划分建议按功能切不要按“画图方便”切。常见拆法是clk_div负责把系统时钟降到消抖和扫描用的慢时钟key_sync做按键同步和 20 ms 消抖note_lut把键值转成频率控制字或计数上限tone_gen产生对应音符的方波out_drive做蜂鸣器或音频输出级。每个子图单独建.bdf画完后生成.bsf符号文件顶层再放符号、连线。具体操作上先画子图再生成符号最后回顶层实例化。子图修改后要重新生成符号否则顶层调用的还是旧引脚定义这是原理图流程里最容易被忽略的一步。总线命名要统一比如键值用key_val[3:0]频率字用freq_word[17:0]不要在子图里叫note[3..0]顶层又叫key_code[3..0]编译时不会报错但连出来是悬空的。子图输入输出关键参数clk_divclk_50m、rst_nclk_1k、clk_scan分频系数按 1 ms 或 10 ms 扫描周期算key_synckey[7:0]、clk_scankey_val[3:0]、key_valid两级同步 20 ms 计数消抖note_lutkey_val[3:0]freq_word[17:0]查表或组合逻辑译码空键输出静音tone_genclk_50m、freq_wordbeep计数器上限 f_clk/(2f)-1out_drivebeep、key_validbeep_out三极管驱动必要时加 RC 滤波顶层连线时输入端口先接同步模块不要直接把按键送进译码器。译码器输出频率字后最好打一拍再送计数器避免组合逻辑毛刺造成音符切换时“咔哒”一声。输出级如果驱动无源蜂鸣器beep直接给方波即可如果驱动有源蜂鸣器它只会按固定频率响换音符没有意义这一点在选件时就要确认。2.3 编译前检查层次、未连接引脚和总线命名编译前先看三处顶层实体是否指向organ_top所有子图是否已经加入工程符号文件是否是最新生成。Quartus 的 Messages 窗口里Analysis Synthesis 的警告比 Error 更值得看尤其是“未连接输入”“输出多个驱动”“总线位宽不匹配”这几类。未连接输入在原理图里会默认接一个电平但不同器件、不同设置下行为不一定一样稳妥做法是显式接GND或VCC。总线命名要逐段核对。比如freq_word[17..0]在顶层用总线画出子图端口也必须是 18 位如果子图只画了 16 位编译可能只给警告但高位被截掉高音区会明显偏。未用引脚在工程设置里统一设为三态输入或按板卡要求处理不要让它悬空。编译通过后先看 Pin-Out 报告确认时钟、复位、蜂鸣器、按键都落在预期引脚上再进下载环节。提示原理图工程里最贵的不是画图时间而是“改完子图忘了更新符号”之后的排查时间。每次改子图端口先重新生成符号再编译顶层。3. 音符频率与音频输出原理图里的参数怎么算、怎么连电子琴的音准不是调出来的是算出来的。系统时钟经过计数器分频得到方波方波频率决定音高计数上限差几个数听感未必明显但计数上限按整周期算错就会差一个八度。原理图里做音符生成常见两种方案一种是每个音符一个计数上限计数器数到上限翻转输出另一种是相位累加器加查找表适合多音和精细调节。前者连线直观适合原理图入门后者精度高但 24 位或 32 位加法器在原理图里会占很大图面。我一般会先用计数器方案把单音电子琴跑通再考虑把tone_gen换成参数化符号。这样调试时只看一个计数器和一根输出线出了问题也容易定位。音频输出级不要直接拿 FPGA 引脚去推蜂鸣器普通 IO 的驱动能力有限无源蜂鸣器启动电流可能把电压拉低表现就是“按键一按系统复位”或者声音发虚。3.1 系统时钟到音符频率分频系数与相位累加器选型方波分频的公式是计数上限N round(f_clk / (2 × f_note)) - 1。计数器从 0 数到 N 后清零同时输出翻转一次这样输出周期就是2 × (N1)个时钟周期频率为f_clk / (2 × (N1))。如果误用f_clk / f_note作为上限输出会低一个八度如果计数器位宽不够数到一半溢出声音会变成杂音。以 50 MHz 时钟为例中音 C4 到 C5 的参数可以这样取音符标称频率/Hz计数上限 N实际频率/Hz误差C4261.6395553261.63约 0D4293.6685132293.66约 0E4329.6375838329.640.01F4349.2371585349.23约 0G4392.0063775392.00约 0A4440.0056817440.00约 0B4493.8850619493.88约 0C5523.2547778523.24-0.01表里的 N 是按 50 MHz 算的换晶振就要整表重算。计数器位宽按最大 N 取低音区 N 可能接近 20 万18 位计数器够用如果只做中高音17 位也能覆盖但不要卡着最大值选位宽留一点余量。相位累加器方案的频率控制字是FCW round(f_note × 2^N / f_clk)精度高但原理图里做 32 位加法器不划算除非后面要加多音混合。注意分频参数表要和工程里的时钟频率绑定。板上晶振是 50 MHz代码里却按 25 MHz 算所有音符会低一个八度这种问题靠听感很难第一次发现。3.2 按键消抖与多键优先级原理图连线的时序边界机械按键的抖动时间常见在几毫秒到十几毫秒消抖计数按 20 ms 设计比较稳。50 MHz 下 20 ms 对应 1,000,000 个时钟周期计数器取 20 位。按键先经过两级触发器同步到系统时钟域再用使能信号驱动消抖计数器计数满后如果按键仍保持按下才更新键值。消抖后的键值最好再寄存一拍再送优先编码器避免组合逻辑毛刺直接进音符译码。多键同时按下时要有明确优先级。常见做法是低音优先或高音优先选一种并在图里固定下来不要让它随连线顺序变化。原理图里可以用优先编码器宏单元也可以自己用与门、或门搭自己搭的时候注意每个键的valid要参与编码否则松键瞬间会短暂输出一个错误键值。按键极性也要在顶层统一低有效按键先取反再进消抖不然后面译码表全是反的。参数建议值说明同步级数2 级降低亚稳态概率消抖时间20 ms50 MHz 下计数 1,000,000消抖计数器位宽20 位留余量不要刚好卡满键值寄存1 拍抑制组合逻辑毛刺多键策略固定优先级低音优先或高音优先二选一3.3 蜂鸣器/PWM 输出级占空比、驱动能力和滤波蜂鸣器先分有源和无源。有源蜂鸣器内部有振荡电路给直流电平就响频率固定不能用来演奏无源蜂鸣器需要外部方波方波频率决定音高电子琴必须用无源蜂鸣器。输出级常见做法是用三极管或 MOS 管驱动FPGA 引脚只给基极或栅极信号基极串限流电阻感性负载两端加续流二极管。直接把蜂鸣器接到 IO 上轻则声音小重则 IO 过流。如果输出到音频座方波谐波多听感偏刺耳可以加一级 RC 低通。RC 截止频率要高于最高音符的基频同时低于 PWM 载波频率。比如用 1 kΩ 加 4.7 nF截止频率约 33.9 kHz能保留音频基波并滤掉一部分高频毛刺电容再大就会把高音区削弱。PWM 调音量时载波频率至少取音频最高频率的 10 倍以上占空比按音量等级变化但无源蜂鸣器直接方波驱动时占空比通常保持 50%。输出方式适用场景关键参数注意IO 直推仅限小电流蜂鸣器电流 IO 额定值不推荐容易拉低电源三极管驱动无源蜂鸣器基极电阻按 β 算加续流二极管RC 滤波音频座输出截止频率 20 kHz电容不要过大PWM 调音量需要音量等级载波 ≥ 10 倍音频占空比与音量对应3.4 仿真验证用波形观察分频和音符切换仿真先做功能仿真不跑时序。新建波形文件把clk_50m周期设成 20 ns复位拉低几个周期再释放然后给key[0]一个按下动作观察key_val是否在 20 ms 后更新freq_word是否切到对应音符beep的周期是否接近目标频率。仿真时间不用一开始就跑满几秒先跑 100 ms 看消抖和音符切换再跑 1 s 看长时间稳定性。仿真时最容易漏的是复位释放时刻和按键初始电平。按键如果默认低有效初始值要给高复位如果低有效初始值要给低。波形里看到freq_word频繁跳变通常是消抖没生效或者组合逻辑毛刺没打拍。功能仿真通过后再做时序仿真重点看时钟到输出延时和建立保持关系电子琴这种低速外设一般不会卡时序但时钟走线、分频器复位和跨时钟域按键同步要确认。4. 引脚分配、下载与板级联调从编译通过到真的响编译通过只说明逻辑连上了离“真的响”还差引脚分配、IO 标准和板级确认。引脚分配错一位蜂鸣器可能接到数码管位选上IO 标准填错下载后可能时好时坏时钟源没确认音准整体偏。板级联调要按信号链从前往后查先测时钟再测复位再测按键最后测输出不要一上来就怀疑音符表。我一般会把引脚约束单独留一份表按板卡手册逐脚核对改完一处勾一处。引脚分配不要靠记忆尤其是不同封装下同一个信号名可能落在完全不同的引脚上。下载前先看编译报告里的 Pin-Out 文件下载后再用万用表或示波器确认关键点比反复改代码快得多。4.1 引脚约束与IO标准按实验板手册逐脚核对先在 Pin Planner 里把顶层端口全部列出来再按板卡手册填引脚号。时钟尽量用专用时钟输入脚复位和按键用普通 IO蜂鸣器输出确认板上是否有三极管驱动。IO 标准按板卡 IO 电压填常见是 3.3 V LVTTL 或 LVCMOS如果板卡是 5 V 器件FPGA 输出到 5 V 输入端要做电平转换不要直接接。信号方向板卡资源约束注意clk_50m输入板载晶振专用时钟脚确认频率rst_n输入复位按键确认低有效或高有效key[7:0]输入独立按键上拉或下拉按原理图beep输出蜂鸣器驱动脚确认是否有三极管seg[7:0]输出数码管段选共阴共阳匹配dig[3:0]输出数码管位选扫描频率不要过低未用引脚在工程设置里统一处理设为三态输入或按板卡要求输出低电平。不要让它悬空悬空输入会增加功耗也可能让下载后行为不稳定。引脚分配完成后重新全编译看 Fitter 报告里有没有引脚冲突、IO 标准不匹配和时钟网络警告。4.2 下载配置与时钟源确认下载前先确认下载器连接正常Programmer 里能看到目标器件。配置文件用.sof可以直接下载到器件内部掉电后丢失要掉电保存需要生成.pof并烧写到板上的配置芯片具体支持哪种方式看板卡。下载后按一次复位再按键测试。如果下载成功但不响先测时钟脚有没有波形再测复位脚电平最后测蜂鸣器驱动脚有没有方波。时钟源确认这一步不能省。板载晶振标称 50 MHz实际可能有偏差但一般不会大到影响音阶更常见的是工程里填了 50 MHz板上却是 25 MHz 或 27 MHz。用频率计或示波器测一下时钟脚把实测值代回分频表。PLL 输出时钟也要确认锁定信号和输出频率不要只看原理图上的标称值。4.3 用Tcl脚本固化工程设置引脚和工程设置改多了很容易出现“这台机器上能编译换台机器就报错”。可以把关键设置写成 Tcl 脚本在 Quartus Tcl Console 里逐段执行。下面脚本里的引脚占位符必须按板卡手册替换不要直接照抄。# 先备份工程目录下的 .qsf再在 Quartus Tcl Console 中逐段执行 project_open ./organ_top.qpf # 顶层实体和未用引脚处理方式 set_global_assignment -name TOP_LEVEL_ENTITY organ_top set_global_assignment -name RESERVE_ALL_UNUSED_PINS AS INPUT TRI-STATED # 时钟、复位、蜂鸣器引脚PIN_xxx 按板卡手册替换 set_location_assignment PIN_CLK_PLACEHOLDER -to clk_50m set_location_assignment PIN_RST_PLACEHOLDER -to rst_n set_location_assignment PIN_BEEP_PLACEHOLDER -to beep # 按键总线按位分配花括号防止 Tcl 解析方括号 set_location_assignment PIN_KEY0_PLACEHOLDER -to {key[0]} set_location_assignment PIN_KEY1_PLACEHOLDER -to {key[1]} # IO 标准按板卡 IO 电压填写3.3-V LVTTL 只是示例 set_instance_assignment -name IO_STANDARD 3.3-V LVTTL -to clk_50m set_instance_assignment -name IO_STANDARD 3.3-V LVTTL -to beep project_close这段脚本的作用是把顶层实体、未用引脚策略、引脚位置和 IO 标准固定下来。PIN_CLK_PLACEHOLDER这类名字是占位符必须替换成板卡手册上的真实引脚号RESERVE_ALL_UNUSED_PINS设为三态输入是常见做法但如果板卡要求未用引脚输出低就按板卡改。执行前先备份.qsf脚本跑完后重新打开工程编译确认 Pin-Out 报告与预期一致。5. 避坑与排查原理图电子琴最容易翻车的五处原理图电子琴的坑大多不在“图会不会画”而在“参数和器件边界有没有对齐”。下面五条是血泪经验里出现频率最高的每条都按现象、原因、解决写照着排查能少走很多弯路。5.1 编译通过但蜂鸣器不响先分清有源和无源现象是工程全编译通过下载后按键有反应数码管也跳但蜂鸣器一点声音没有。先看蜂鸣器类型有源蜂鸣器给直流就响给方波反而可能只是断续咔哒无源蜂鸣器必须给对应频率的方波给直流不响。再看驱动脚有没有方波如果引脚有波形但蜂鸣器不响检查三极管方向、基极电阻和续流二极管如果引脚没有波形检查tone_gen的使能条件和音符译码输出。还有一种情况是输出脚被分配到了板卡上没有连接的引脚编译报告里看不出来下载后自然没反应。解决方法是先测驱动脚波形再对照板卡原理图确认蜂鸣器接法最后确认 IO 标准。不要一上来就改音符表先证明信号到了蜂鸣器。5.2 音不准或整体低一个八度分频公式和时钟频率对不上现象是每个音符都能响但整体偏低或偏高八度关系不对。最常见原因是分频上限用了f_clk/f_note而方波翻转需要f_clk/(2f_note)其次是工程时钟频率填错板上是 25 MHz分频表按 50 MHz 算还有就是计数器位宽不够高音区数不到上限就溢出。解决时先把clk_50m实测频率代回公式再逐个核对计数上限和位宽。如果只有高音区偏低音区正常优先查计数器位宽和比较器位宽如果所有音符按固定比例偏查时钟频率如果个别音符偏查该音符的查表值是不是抄错。音准问题不要靠耳朵反复试拿波形仿真量周期最快。5.3 按键乱响、连击或松键瞬间变音消抖和优先级没锁死现象是按一下键响好几声或者松键瞬间跳到另一个音。原因通常是按键没有同步和消抖机械抖动被当成多次按键或者多键优先级没有固定组合逻辑在键值变化时产生毛刺。解决方法是加两级同步、20 ms 消抖计数和一拍寄存再把消抖后的键值送优先编码器。按键极性也要统一低有效按键先取反再进消抖。如果只有多键同时按才乱检查优先编码器的使能端和无效键处理如果单键也乱检查消抖时钟是否真的在跳以及复位是否把计数器清干净。消抖计数器不要用组合逻辑输出直接当键值最好在计数满时打一拍。5.4 下载后时好时坏、一碰就复位电源和 IO 标准在报警现象是下载后能响但声音一大就复位或者手碰板子就变。原因可能是蜂鸣器直接由 IO 驱动启动电流把电源拉低也可能是 IO 标准与板卡电压不匹配或者未用引脚悬空。解决方法是加三极管驱动、检查电源去耦、把未用引脚设为三态输入并按板卡 IO 电压设置 IO 标准。时钟脚如果走了普通 IO也可能引入抖动优先换到专用时钟脚。这类问题靠改逻辑很难解决先量电源和地再量驱动脚电流。蜂鸣器两端加续流二极管基极电阻不要省。下载线太长或接触不良也会造成配置失败换短线、重新插紧再试。5.5 子图改了顶层不生效符号文件没有更新现象是明明改了子图的计数上限编译后声音没变或者子图端口改了顶层编译报宽度不匹配。原因是原理图符号.bsf还是旧版本顶层调用的是旧符号。解决方法是每次修改子图端口或参数后重新生成符号文件再回顶层更新实例。文件名大小写也要一致有些系统对大小写不敏感换系统后才暴露问题。改完子图后先单独编译子图再编译顶层看 Messages 里有没有“符号过期”类警告。顶层不要保留多个同名实例总线位宽逐段核对。原理图流程里符号就是接口合同合同改了不重新签顶层当然对不上。6. 进阶用法把原理图电子琴改成可验证的模板把单音电子琴跑通之后下一步不是盲目加功能而是把参数收拢成可替换的符号。我一般会把tone_gen里的计数上限做成输入端口顶层用常量或查找表驱动把消抖时间做成parameter不方便时就用一个独立子图debounce_cfg输出计数上限。这样换晶振只需要改一张参数表不用满图找比较器。再加自动演奏可以用一个节拍计数器扫描音符表节拍间隔按 120 BPM 算四分音符约 500 ms用慢时钟分频得到使能信号逐条读出音符和时值。验证时按三层走功能仿真看分频周期和按键切换时序仿真看时钟到输出延时板级测试先测时钟、复位、按键、蜂鸣器四个点。每次改参数先跑一遍单音 C4再跑一遍高音 C5最后试多键优先级。从那以后我每次改分频表都强制走一遍“实测时钟—重算计数—仿真周期—板级听音”的流程不再凭耳朵判断。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站