基于cpld的简易电子琴的设计内容摘要:

/输出 Pin 4 ~Pin11 适配器上侧 Pin 4 ~Pin11 8个 I/O 可编程输入 /输出 CLK1 适配器左上方 83 CLK1 全 局 时钟 输入 Clk2 2 CLk2 全 局 时钟 输入 电子科技大学成都学院 12 CLRn 1 Reset 全 局 清零 输入 OE1n 84 OE 全 局 使能 输入 注: Altera 公司的 FLEX10K10 适配器与上述相似 其中 CLRn=3, OE=83, CLK1=43, CLK0=1 在最终设计编译后,确定此次设计使用 EMP7128S 芯片是可行的。 如图 211 图 212 EPM7128S 芯片的编译报告 第 3 章 软件设计 13 第 3章 软件设计 分频器的设计 概述 分频器是数字电路中最常用的电路之一,在 FPGA 的设计 中也是使用效率非常高的基本设计。 基于 FPGA 实现的分频电路一般有两种方法:一是使用FPGA 芯片内部提供的锁相环电路,如 ALTERA 提供的 PLL( Phase Locked Loop), Xilinx 提供的 DLL( Delay Locked Loop);二是使用硬件描述语言,如VHDL、 Verilog HDL 等。 使用锁相环电路有许多优点,如可以实现倍频;相位偏移;占空比可调等。 但 FPGA 提供的锁相环个数极为有限,不能满足使用要求。 因此使用硬件描述语言实现分频电路经常使用在数字电路设计中,消耗不多的逻辑单 元就可以实现对时钟的操作,具有成本低、可编程等优点。 计数器 计数器是实现分频电路的基础,计数器有普通计数器和约翰逊计数器两种。 这两种计数器均可应用在分频电路中。 最普通的计数器是加法(或减法)计数器。 下面是加法计数器的 VHDL 实现: library ieee。 use。 use。 use。 entity ripple is generic (width: integer := 4)。 port(clk, rst: in std_logic。 t: out std_logic_vector(width 1 downto 0))。 end ripple。 architecture a of ripple is signal tQ: std_logic_vector(width 1 downto 0)。 电子科技大学成都学院 14 begin process(clk, rst) begin if (rst = 39。 139。 ) then tQ = (others = 39。 039。 )。 elsif (clk39。 event and clk = 39。 139。 ) then tQ = tQ + 1。 end if。 end process。 t = tQ。 end a。 在同一时刻,加法计数器的输出可能有多位发生变化,因此,当使用组合逻辑对输出进行译码时,会导致尖峰脉冲信号。 使用约翰逊计数器可以避免这个问题。 约翰逊计数器 约翰逊计数器是一种移位计数器,采用的是把输出的最高位取非,然后反馈送到最低位触发器的输入端。 约翰逊计数器在每个时钟下只有一个输出发生变化。 下面是约翰逊计数器的 VHDL 实现代码。 file Name: Description: 带复位功能的约翰逊计数器 library ieee。 use。 use。 use。 entity johnson is generic (width: integer := 4)。 第 3 章 软件设计 15 port (clk, rst: in std_logic。 t: out std_logic_vector(width 1 downto 0))。 end johnson。 architecture a of johnson is signal tQ: std_logic_vector(width 1 downto 0)。 begin process(clk, rst) begin if(rst = 39。 139。 ) then tQ = (others = 39。 039。 )。 elsif (rising_edge(clk)) then tQ(width 1 downto 1) = tQ(width 2 downto 0)。 tQ(0) = not tQ(width 1)。 end if。 end process。 t = tQ。 end a。 显然,约翰逊计数器没有有效利用寄存器的所有状态,假设最初值或复位状态为此 0000,则依次为 0000、 000 001 011 111 11 1100、 1000、0000 如循环。 再者,如果由于干扰噪声引入一个无效状态,如 0010,则无法恢复到有效到循环中去,需要我们加入错误恢复处理,在此不再赘述。 分频器 如前所述,分频器的基础是计数器,设计分频器的关键在于输出电平翻转的时机。 下面使用加法计数器分别描述各种分频器的实现。 偶数分频最易于实现,欲实现占空比为 50%的偶数 N 分频,一 般来说有两种方案:一是当计数器计数到,当计数器计数到 N/21 时,将输出电平进行一次翻转,同时给计数器一个复位信号,如此循环下去;二是当计数器输出为 0 到电子科技大学成都学院 16 N/21 时,时钟输出为 0 或 1,计数器输出为 N/2 到 N1 时,时钟输出为 1 或0N1 时,复位计数器,如此循环下去。 需要说明的是,第一种方案仅仅能实现占空比为 50%的分频器,第二种方案可以有限度的调整占空比,参考非 50%占空比的奇数分频实现。 在本文中,使用第一种方案实现分频。 用下面 VHDL 代码实现占空比为 50%的分频: 6 分频 library ieee。 use。 use。 use。 entity clk_div1 is port(clk_in: in std_logic。 clk_out: out std_logic)。 end entity clk_div1。 architecture a of clk_div1 is signal clk_outQ: std_logic :=39。 039。 赋初始值仅供仿真使用 signal countQ: std_logic_vector(2 downto 0) := 000。 begin process(clk_in) begin if(clk_in’event and clk_in=’1’) then if(countQ/=2) then countQ= countQ+1。 else clk_outQ = not clk_outQ。 第 3 章 软件设计 17 countQ = (others =’0’)。 end if。 end if。 end process。 clk_out = clk_outQ。 end architecture a。 仿真图如下: 基于分频器的电子琴设计 概述 电子琴基本模块的核心内容是分频器。 其中 有两个分频器,一个是基频分频计数器,将时钟信号分频至较小的频率 ,便于二次分频 ;另一个是音阶分频计数器,由基频分频产生各个音阶。 流程如图 32。 音阶分频器的敏感参数是可以是时钟信号或基频分频出的信号。 两次分频的嵌套叠加产生合适的音阶频率,驱动蜂鸣器发声,实现电子琴的基本部分。 音阶分频器还具有检验琴键输入信号的作用,以便能依据琴键信号做出正确的响应。 音阶分频器还具有控制数码管显示与琴键相应数值,和当高音“多”时驱动彩灯发光指示的能力。 图 31 50%占空比 6 分频仿真图 电子科技大学成都学院 18 自顶向下电子琴设计探讨 自顶向下设计电子琴可分为自动 手动 演奏 选择 ,基频分频,和音阶分频 发声显示 三部分。 a u t ocl ki n d e x 2 [ 7 . . 0 ]i n d e x 0 [ 7 . . 0 ]cl kr stcl k _ d i v 5 [ 3 . . 0 ]i n d e x [ 7 . . 0 ]h i g h 1o u t _ b i tl e d 7 [ 6 . . 0 ]cl kr stcl k _ d i v [ 3 . . 0 ]a u t oh i g h 1o u t _ b i tke y i n [ 7 . . 0 ]l e d 7 [ 6 . . 0 ]f re s p e : U 2cl k1rs t 1a u t o 1 : U 1f re : U 3图 33 电子琴 RTL 电路图 rst 是否为 1 进入 /清零 琴键输入 基频分频 12MHz 时钟信号 音阶分频 显示,发声 图 32 流程图 第 3 章 软件设计 19 自动手动演奏选择模块 自动手动演奏选择模块是个控制开关。 控制发声部分是否按自动演奏或者手动演奏发声。 自动 手动 演奏 选择模块 主要 VHDL 代码 如下 : entity auto1 is port ( clk: in std_logic。 auto: in std_logic。 q : buffer std_logic。 index2: in std_logic_vector(7 downto 0)。 index0: out std_logic_vector(7 downto 0))。 end auto1。 architecture beh of auto1 is CONSTANT duo : std_logic_vector(7 DOWNTO 0) := 11111110。 CONSTANT lai : std_logic_vector(7 DOWNTO 0) := 11111101。 CONSTANT mi : std_logic_vector(7 DOWNTO 0) := 11111011。 CONSTANT fa : std_logic_vector(7 DOWNTO 0) := 11110111。 CONSTANT suo : std_logic_vector(7 DOWNTO 0) := 11101111。 CONSTANT la : std_logic_vector(7 DOWNTO 0) := 11011111。 CONSTANT xi : std_logic_vector(7 DOWNTO 0) := 10111111。 CONSTANT duo1 : std_logic_vector(7 DOWNTO 0) := 01111111。 signal count0: integer range 0 to 7。 begin pulse0:process(clk,auto) variable count: integer range 0 to 8。 begin if auto=39。 139。 then 电子科技大学成都学院 20 count:=0。 q=39。 039。 elsif(clk39。 event and clk=39。 139。 ) then count:=count+1。 if count=4 then q=39。 139。 elsif count=8 then q=39。 039。 count:=0。 end if。 end if。 end process。 music:process(q) begin if (q39。 event and q=39。 139。 ) then if (count0=7) then count0=0。 else count0=count0+1。 end if。 end if。 end process。 1:process(count0,auto,index2) begin if auto=39。 039。 then case count0 is when 0=index0=duo。 when 1=index0=xi。 第 3 章 软件设计 21 „„ when others=null。 end case。 else index0=index2。 end if。 end proce。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。