PLD与数字系统设计实验 旋钮开关.docx
PLD与数字系统设计实验报告实验二(B组):旋转开关一 实验要求:利用Spartan-3 Starter Board实验板上的旋转开关,设计一个通过旋转开关的方向来控制LED灯的依次点亮顺序的实验,并且要求可以循环点亮。二 实验原理及算法分析本次实验总体上来讲可以分为两大部分来思考:第一部分为由旋转旋钮的方向决定LED灯点亮的顺序,使实现旋钮向右旋转时LED灯向右点亮,旋钮向左旋转时LED灯向左点亮,这部分的关键在于如何根据电路板的引脚输入判断旋钮旋转的方向;第二部分为通过旋转旋钮构建时钟来实现旋钮旋转一格时可循环地依次点亮一个LED灯,关键在于如何构建实验所需要的时钟。1°旋钮方向下面这幅图取自Xilinx UG230 Spartan-3E Starter Kit Board User Guide,是Spartan-3电路板上的旋钮的编码电路图:上页图所示的是旋钮旋转中A、B两个引脚的一个状态,实际中旋钮旋转一格使A和B与GND导通的开关(分别记为K1、K2)的状态变化(K1、K2)分别为:向右旋转时:(断开,断开)(闭合,断开)(闭合,闭合)(断开,闭合)(断开,断开)向左旋转时:(断开,断开)(断开,闭合)(闭合,闭合)(闭合,断开)(断开,断开)根据用户手册中A、B两个引脚的UCF文件所述:“NET "ROT_A" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP;NET "ROT_B" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP;”Vcco接高电平,当K1断开时,A输出为高电平,即输出为“1”;当K1闭合时,A输出为低电平,即输出为“0”。对B同理可得出相同结果。可得到旋钮旋转一格(A,B)状态的变化如下:向右旋转时:(1,1)(0,1)(0,0)(0,1)(1,1)向左旋转是:(1,1)(1,0)(0,0)(0,1)(1,1)因此可以根据A、B两个引脚输入值的变化来判断旋钮的旋转方向,主要依据的状态为状态2和状态4。下图为用户手册中的关于旋钮向右旋转时的A、B引脚的电平变化时序图,仅供参考(注:实际中经过实验测试A、B两个引脚的初始态应该是高电平、高电平):由上图可以看出,引脚电平变化时会出现抖动现象(实际上按键抖动是机械按键和旋钮的普遍现象)。实验中所用电板的时钟频率为50MHz,须使用分频降低频率获得新的更大周期的时钟来避免受到抖动的影响。2°可循环地依次点亮LED灯为了得到可通过旋转旋钮构建可实现旋钮旋转一格时可循环地依次点亮一个LED灯的按钮的时钟CLK,可以令下一个LED灯亮的动作发生在CLK的上升沿,由1°中的分析可知,旋钮旋转一格总共经历五个状态,可以设置CLK初始状态为“1”,当得到前三个状态时,改变CLK状态为“0”,当到达第四个状态时就可以对点亮LED灯的方向做出判断,当到达某一格的第五个状态(也可以看成是下一个的第一个状态)时,改变CLK状态为“1”,这就得到了旋转一格控制LED点亮的时钟过一个周期的效果。根据用户手册中LED灯的UCF文件所述:NET "LED<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;LED驱动强度为“8”,为高电平点亮。所以对LED灯可循环地依次点亮的实现,可以通过控制8个LED灯的电平来实现,这个比较简单,代码实现见实验报告“三 实验算法及核心代码实现”。三 实验算法及核心代码实现1°分频CLK介于分频在实际应用中的重要性,在此给出本次实验中用到的分频实现代码:input clk;integer i;reg CLK;parameter count = 10_0000;always ( posedge clk ) beginif ( i = count ) begini = 0;CLK =CLK;endelse i = i + 1;endclk为电路板的50MHz时钟,上面的代码很好的实现了50M/(50M/count)Hz频率的时钟。通过合理调节CLK频率即可有效避免抖动的影响,如上,实验所用count = 10_0000。2°旋钮方向判断及得到依次点亮LED灯的时钟clk0以fir,sec记录AB第二个和第四个状态的值,据此作出判断依据,这里在clk0从“0”变到“1”放在第三个状态而不放在第四个状态可以避免order和clk0上升沿发生竞争:always ( posedge CLK ) begincase ( ab , fir , sec )/第一种情况,向右旋转6'b11_00_00: clk0 = 1;6'b01_00_00: fir = 2'b01;6'b00_01_00: clk0 = 0;6'b10_01_00: beginsec = 2'b10;order = 2'b01;/LED灯向右点亮end6'b11_01_10: beginfir = 2'b00;sec = 2'b00;clk0 = 1;end/第二种情况,向左旋转/6'b11_00_00: clk0 = 1;6'b10_00_00: fir = 2'b10;6'b00_10_00: clk0 = 0;6'b01_10_00: beginsec = 2'b01;order = 2'b10; /LED灯向右点亮end6'b11_10_01: beginfir = 2'b00;sec = 2'b00;clk0 = 1;endendcaseend3°可循环地依次点亮LED灯利用case语句来实现,如右移:case ( order ) 2'b01:/右移case ( temp )8'b1000_0000: temp = 8'b0100_0000 ;8'b0100_0000: temp = 8'b0010_0000 ;8'b0010_0000: temp = 8'b0001_0000 ;8'b0001_0000: temp = 8'b0000_1000 ;8'b0000_1000: temp = 8'b0000_0100 ;8'b0000_0100: temp = 8'b0000_0010 ;8'b0000_0010: temp = 8'b0000_0001 ;8'b0000_0001: temp = 8'b1000_0000 ;endcase四 实验结果每向左旋转一格旋钮,LED亮灯依次向左传递一个,每向右旋转一格旋钮,LED亮灯依次向右传递一个,可实现循环点亮,与期望结果一致。附1:实验源代码module rotation(clk,A,B,led);input clk,A,B;output 7:0 led;wire 1:0 ab;reg 1:0 fir,sec,order;integer i;reg CLK,clk0;reg 7:0 temp;parameter count = 10_0000;assign ab = A , B ;assign led = temp;initial beginfir = 2'b00 ;sec = 2'b00 ;order = 2'b00;i = 0;CLK = 0;clk0 = 1;temp = 8'b0000_1000;end/分频always ( posedge clk ) beginif ( i = count ) begini = 0;CLK =CLK;endelse i = i + 1;end/判别旋转过程并设置clk0always ( posedge CLK ) begincase ( ab , fir , sec )/第一种情况,向右旋转6'b11_00_00: clk0 = 1;6'b01_00_00: fir = 2'b01;6'b00_01_00: clk0 = 0;6'b10_01_00: beginsec = 2'b10;order = 2'b01;end6'b11_01_10: beginfir = 2'b00;sec = 2'b00;clk0 = 1;end/第二种情况,向左旋转/6'b11_00_00: clk0 = 1;6'b10_00_00: fir = 2'b10;6'b00_10_00: clk0 = 0;6'b01_10_00: beginsec = 2'b01;order = 2'b10;end6'b11_10_01: beginfir = 2'b00;sec = 2'b00;clk0 = 1;endendcaseend/旋转点亮LED灯always ( posedge clk0 ) begincase ( order ) 2'b01:/右移case ( temp )8'b1000_0000: temp = 8'b0100_0000 ;8'b0100_0000: temp = 8'b0010_0000 ;8'b0010_0000: temp = 8'b0001_0000 ;8'b0001_0000: temp = 8'b0000_1000 ;8'b0000_1000: temp = 8'b0000_0100 ;8'b0000_0100: temp = 8'b0000_0010 ;8'b0000_0010: temp = 8'b0000_0001 ;8'b0000_0001: temp = 8'b1000_0000 ;endcase2'b10:/左移case ( temp )8'b0000_0001: temp = 8'b0000_0010 ;8'b0000_0010: temp = 8'b0000_0100 ;8'b0000_0100: temp = 8'b0000_1000 ;8'b0000_1000: temp = 8'b0001_0000 ;8'b0001_0000: temp = 8'b0010_0000 ;8'b0010_0000: temp = 8'b0100_0000 ;8'b0100_0000: temp = 8'b1000_0000 ;8'b1000_0000: temp = 8'b0000_0001 ;endcaseendcaseendendmodule附2: 引脚分配文件代码NET "clk" LOC = "C9" | IOSTANDARD = LVCMOS33;NET "A" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP;NET "B" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP;NET "led7" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led6" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led5" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led4" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led3" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led2" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led1" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;NET "led0" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8;