1、EDA 实验一实验报告一、实验设计思路1、键盘输入状态机设计控制键盘输入的电路分为 5 个模块:(1)扫描信号电路其状态转换图如下:状态根据扫描频率自动跳转,在 S0S3 状态下分别输出 0001、1000 、0100、0010 ,该电路的输出用于数码管的选通(接位选线)和键盘信号的检测(接 H) 。(2)键值信号电路该电路的功能是输出按键对应的值,按键按下时,就跳到键值相应的状态,并输出相应的值。(3)按键信号电路电路的状态转换图如下:当数字按键被按下时,状态跳转到 S1 并输出高电平,如果不长按键,等一小段时间后,状态会自动回到 S0 并输出低电平。如果长按键,那么状态会停留在 S1 处,
2、这样就不会重复地输出按键信号了。(4)运算符号电路状态转换图如下:该电路的功能是记录运算符号,按下符号按键就跳转到相应的状态,S0 为初始状态,输出为 000,当按下数字键时,任何状态都会跳转回 S0;S1 、 S2、S3、S4 和 S5 分别为加、减、与、或和比较运算对应的状态,输出分别为 001、010、011、100、101 ;S6 为按下等号键会跳转到的状态,输出为 110。(5)控制电路该电路的功能是选择移位寄存器、得到清零信号。当第一次输出数字是,control 选通其中一个移位寄存器;当按下运算符号时,电路跳转到下一个状态,control 选通另外一个移位寄存器。清零信号在按下等
3、号键(正常规则下)或在得到运算结果后再次输入时,将移位寄存器的数据和运算符号等清空。2、 ALU 运算逻辑ALU 完成高 8 位和低 8 位运算的状态转换图,实际上是 Process 模块的状态转换图。在设计里,ALU 只要求完成 8 位二进制数的运算,其进位、借位的处理由 Process 模块执行。状态转换图如下(Process 模块程序中的 S6、S7 是无用的状态,这里不画出):(1)状态含义及跳转条件:S0 为初始状态,按下数字键或等号键时,停留在 S0;按下运算符号键(下称符号键)时,跳转到 S1。在 S1 状态下,按下数字键或符号键时,停留在 S1,并取最后输入的运算符号;按下等号
4、键时,跳转到 S2。在 S2 状态下,按下等号键停留在 S2,按下数字键跳转到 S1,按下符号键跳转到 S5,S5 是一个记录运算结果用的状态,在 S5 会立刻跳转到 S3。S3 和 S4的含义和跳转条件与 S1、S2 类似,是进行继续运算用的状态。当 Reset 键被按下时,状态S1S4 都会跳转回状态 S0。(2)各状态下的数据输出:S1 状态下,输出给 ALU 模块的数是两个数(记为 A、B)的低 8 位,carry_in 根据运算符号设置,加法为 0,减法为 1。S2 状态下,输出给 ALU 模块的数是 A、B 的高 8 位,carry_in则取 S1 状态时 ALU 的 carry_
5、out。对于状态 S3,输出给 ALU 模块的数变为记录了的运算结果的低 8 位和新键入的数的低 8 位,S4 则是两个数的高 8 位,它们的 carry_in 的设置与 S1、S2 类似。(3)ALU 的进位、借位设置:ALU 的进位、借位根据运算符号和前一步的运算结果的正负来判断,运算结果的正负用 D1记录。D1 的初值为 0,当运算结果为非负数时,D1 为 0,当运算结果为负数时,D1 为 1。设计的 ALU 模块是利用补码进行运算的。进行加法运算时,若 D1 为 0,则运算结果的进位和正负判断作通常处理;若 D1 为 1,则对前一步的运算结果取补码再运算,当新的运算结果的符号位为 1
6、时,carry_out 为 1,且carry_in 为 1 时,运算时将加上二进制数 11111111,这其实是向高位借位(符号位为 1,说明运算结果为负,所以要借位) 。当高 8 位运算结果的符号位为 1 时,说明运算结果为负数。进行减法运算时,若 D1 为 0,则借位、结果正负的判断与进行加法运算且 D1 为 1 的情况类似,只是 carry_out 和 carry_in 的 0、1 值调转过来。若 D1 为 1,则将补码相加后,在结果不为 0 的情况下,若符号位为 0 或者符号位为 1 但运算结果为 0 时,carry_out 为 0,其他情况 carry_out 为 1。符号位为 1、
7、运算结果为 0 是指两个负数的低 8 位刚好加起来为-256 的情况,这个时候应该是有借位的。3、显示模块的控制逻辑显示的功能由 Process 模块和 Seg 模块共同实现。其中,Seg 模块的功能主要是将运算结果转换为十进制数,并按顺序显示该数的高位、低位。而 Process 模块的功能则是根据按键的情况选择要显示的数。Process 模块的状态转换图已给出,在 S0 状态下,显示输入的数;在 S1 状态下,在没有输入新数的情况下,显示原来输入的数,输入后显示新输入的数;在 S2 状态下,显示运算结果。对于 S3、 S4,显示的输出类似。对于运算结果的显示,需要根据运算符号和运算结果的正负
8、进行判断。比如,当前一步的结果为非负数,且进行加法运算时,直接显示运算结果;当前一步的结果为非负数,且进行减法运算时,若 carry_out 为 1,则低 8 位的显示要对运算结果取补(得到原码) ,若取补后低 8 位为 0,则高 8 位的显示要取反加一,否则直接取反。4、特殊情况的处理(1)输入超过 3 位:在移位寄存器的 D 触发器中,设置了参数 count,输入一次数,count 加一,输入三次后,count 变为 3,此时触发器的输出不再变化,再输入数也不会被记入寄存器;(2)长按键:长按键的处理涉及到 Clk_test 模块的设计,在该模块中也设置了 count 参数,具体代码如下:
9、always (posedge clks)beginif (H3:0=4b1000)if (V3:0=0)count=count+3b001;elsecount=0;if (H3:0=4b0100)if (V3:0=0)count=count+3b001;elsecount=0;if (H3:0=4b0010)if (V3:0=0)count=count+3b001;elsecount=0;if (H3:0=4b0001)if (V3:0=0)count=count+3b001;elsecount=0;if (count2:0=3b100)count=0;end可见,在长按键的情况下,coun
10、t 不可能达到 100,而状态转换的条件是 count 达到 100,所以长按键时状态不会转换,则输出的信号一直为高电平,不会有新的上升沿出现。(3)非法情况处理:对于连续输入多个运算符号的情况,由于在 Process 模块中的 S1 状态会在未按等号时停留,且实际的运算都在 S1、S2 处进行,所以连续输入多个符号时,实际运算中只取最后一个。对于未输入数便按下符号键的情况,当作 0 与输入的数进行运算,实际上这与计算器对这种情况的处理方法是相同的。对于完成运算后又按等号键的情况,状态不跳转,显示结果仍为原来的结果,这与某些计算器的处理方法不一样,但跟学生用的计算器对于这种情况的处理方法是一样
11、的。5、音乐模块的工作原理(1)音高产生原理蜂鸣器发出的声音的音高,与输入的信号的频率有关,音高对应的频率,可以通过上网搜索得到。将晶振的频率用 cnt 参数降至相应的频率,就能使蜂鸣器发出音高正确的声音。具体代码如下:always (posedge CLK) beginif (cnt111274/2)cnt1=cnt1+1b1;elsebegincnt1=0;do=do;end为了得到频率约为 2217.5Hz 的信号,将 25MHz 的时钟信号分频。其中,25000000 除以11274 就约等于 2217.5,而由于得到信号的逻辑是将信号翻转,在两倍 cnt 从 0 变化到11274 的
12、过程中,信号应翻转两次,所以 11274 要先除以 2,这样得到的信号频率才是正确的。(2)节奏产生原理得到音高对应的信号频率后,为了让蜂鸣器按固定节奏发出声音,可以设计一个状态机电路,并输入一定频率的时钟信号,状态根据该时钟信号按顺序转换,且在不同状态下,电路输出不同频率的信号。这样,蜂鸣器就能“哼”出一段乐曲了。时钟信号的设置,与音高信号的设置类似,但频率要低得多,详见 timer 的设置;电路状态之间的转换,是有一定的规则的,主要是根据乐曲的音长设置,当某音符的音长多于一个时钟周期时,应让该音符占多个状态;当乐曲的某处没有声音发出时,应将输出置为1,使得蜂鸣器在该状态下不发声。二、仿真验
13、证1、键盘输入的仿真波形仿真波形如下:(1)长按键:长按键的情况,就是在 h 为某一个值时,v 总是固定的某一个值,且间隔为一个周期。由波形图可以看出,长按键的情况下,按键信号只会有一个上升沿,且一直保持高电平,直到按键松开才变为低电平(看(2)中的图,在 h 为 1000 的情况下, v 变为了 0000,表明按键已松开,这使得按键信号变为低电平) 。(2)多次按同一键:多次按同一键,按键信号会有多个上升沿,但键值信号不变。(3)按键抖动:该仿真波形图是放大后的图,可见在按键抖动的情况下,按键信号仍是只有一个上升沿。(4)同时按多个键:该仿真波形图模拟了同时按数字键 5、6 、7、8 的情形
14、,可见按键信号仍是只有一个上升沿,尽管键值信号在边,由于上升沿只有一个,能输入到寄存器中的数其实只有最初按下的键对应的那个数。2、 ALU 的仿真波形仿真波形图如下:当 CS 分别为 001、010、011、100 、101 时,ALU 作加法、减法、与、或和比较运算。由于时钟频率设置得较低,结果的变化有延迟。左栏中的倒数第二个是 carry_out,倒数第四个是 carry_in。可见,五种运算下,结果和进位、借位等都是正确的。三、实验总结1、不同实现方法和创新之处说明为了能让蜂鸣器发出两种不同曲调的声音,我设计了两个音高信号发生器,分别命名为NoteDb 和 NoteGb,曲调分别为 Db
15、 和 F#(即 Gb)。根据网上搜到的音高和频率转换表(如下图),很容易得到曲调相应音高的频率。如 Db,它的频率应取表上的2217.5、 2489.0、2793.8、2960.0、3322.4 、3729.3 和 4186.0 等,分别对应do、re 、mi、fa、so、la、xi, F#也可以根据这种规律取频率。2、问题及解决方法(1)设计过程中遇到的一个问题是,何时将储存在寄存器中的数据清零。一开始想要保证运算结果的稳定存在(以便进行后面的继续运算),没有设置适当的清零条件,这使得运算结果不正确。改正后,在得到运算结果以后,若再按等号键,则数据不清零,若按其他键,则数据清零,并事先在 P
16、rocess 模块中把运算结果记录下来,这样就没必要担心清零后运算结果丢失的问题了。(2)设计运算符号电路(PM)时,没有进行充分的考虑,因而没有设置按下数字键或等号键时的 CS 值,导致后面处理电路设计时出现不少麻烦,增加相应 CS 值后又要修改处理电路。这说明设计电路时最好考虑到后续部分电路的设计。(3)设计 ALU 模块时,一开始在没有弄清楚二进制数补码的运算规则的情况下便草率设计,导致问题频现,后来弄清楚符号位和进位、借位以及结果的正负的关系后,才得出所有情况下运算结果都正确的逻辑。(4)设计 Process 模块过程中的一个很大的问题就是,输出给 ALU 模块的变量同时又由 ALU的输出决定,如 D1、q 等,这就有可能形成一个循环,致使运算结果溢出或不正确等的问题。解决方法有多种,可以设置一个中间状态,在中间状态才给这些变量赋值,或者设置一个中间变量等。