回答

收藏

[评测分享] [超越者Spartan-6 FPGA开发板] 按键控制LED灯程序分析及验证

#板卡评测 #板卡评测 2827 人阅读 | 0 人回复 | 2021-05-18

本帖最后由 jinglixixi 于 2021-5-21 13:51 编辑

在开发板配置的例程中,有一个按键控制LED灯的示例,通过它可以学习编程的知识和技巧。此外,通过程序的下载还能验证对程序的分析。
该程序要占用10个引脚资源,分别是:系统时钟sys_clk、系统复位sys_rst_n、4个按键输入及4个LED输出。
系统框图

其模块定义如下:
module key_led(
   input               sys_clk  ,   //50Mhz系统时钟
   input              sys_rst_n,    //系统复位,低有效
   input        [3:0]  key,         //按键输入信号
   output  reg  [3:0]  led           //LED输出信号
   );
此外,还定义了2个寄存器以辅助程序设计,其中cnt用于0.2s的计时器控制,位宽为24位;而led_control则用于状态机的状态存储,其位宽为2位。
相应的寄存器定义如下:
reg [23:0] cnt;
reg [1:0]  led_control;

对应的UCF 约束语句为:
# PlanAhead Generatedphysical constraints
NET"sys_clk" LOC = N8 | IOSTANDARD = "LVCMOS33";
NET"sys_rst_n" LOC = G16 | IOSTANDARD = "LVCMOS33";
NET"led[3]" LOC = T3 | IOSTANDARD = "LVCMOS33";
NET"led[2]" LOC = M7 | IOSTANDARD = "LVCMOS33";
NET"led[1]" LOC = M6 | IOSTANDARD = "LVCMOS33";
NET"led[0]" LOC = T5 | IOSTANDARD = "LVCMOS33";
NET"key[3]" LOC = R3 | IOSTANDARD = "LVCMOS33";
NET "key[2]"LOC = N6 | IOSTANDARD = "LVCMOS33";
NET"key[1]" LOC = N5 | IOSTANDARD = "LVCMOS33";
NET"key[0]" LOC = P5 | IOSTANDARD = "LVCMOS33";
由此便可获知各引脚与FPGA的具体连接关系及供电标准,见下图所示。
引脚连接关系

作为0.2秒计时器的实现,其原理是利用系统时钟,通过程序的计数控制来完成的,因系统时钟为50Mhz,故20ns*10000000=0.2秒。
0.2秒计时程序为:
always @ (posedge sys_clk or negedgesys_rst_n) begin
   if(!sys_rst_n)
       cnt<=24'd9_999_999;
   else if(cnt<24'd9_999_999)
       cnt<=cnt+1;
   else
       cnt<=0;
end
有程序可以看出,在系统复位后,即将延时控制值赋给cnt,在未达到该限值24'd9_999_999
则加1计数,若达到该限值则cnt清零。

那状态机又是如何来工作的呢?
它是利用0.2秒的计时器来工作的,每到0.2秒它就切换一次状态,在系统复位时,它即进入状态0,由于其位宽为2位,故其状态值只有4个,即0~3。
状态机的程序如下:
always @(posedge sys_clk or negedgesys_rst_n) begin
   if (!sys_rst_n)
       led_control <= 2'b00;
   else if(cnt == 24'd9_999_999)
       led_control <= led_control + 1'b1;
   else
       led_control <= led_control;
end

那按键又是如何切换LED灯的显示模式呢?
它是通过判断按键的状态来决定LED灯显示模式,相应的变换节拍受状态机的控制,具体表现为:
当按下按键1 时,是演示从右向左的流水灯效果;当按下按键2时,是演示从左向右的流水灯效果;当按下按键3 时,是演示LED灯的闪烁效果;而按下按键4,则是LED灯全被点亮;若无按键按下,则LED灯被熄灭。
具体的程序内容如下:
always @(posedgesys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
          led<=4'b 0000;
    end
    else if(key[0]== 0)  //按键1按下时,从右向左的流水灯效果
        case (led_control)
            2'b00   : led<=4'b1000;
            2'b01   : led<=4'b0100;
            2'b10   : led<=4'b0010;
            2'b11   : led<=4'b0001;
            default  : led<=4'b0000;
        endcase
    else if (key[1]==0)  //按键2按下时,从左向右的流水灯效果
        case (led_control)
            2'b00   : led<=4'b0001;
            2'b01   : led<=4'b0010;
            2'b10   : led<=4'b0100;
            2'b11   : led<=4'b1000;
            default  : led<=4'b0000;
        endcase
    else if (key[2]==0)  //按键3按下时,LED闪烁
        case (led_control)
            2'b00   : led<=4'b1111;
            2'b01   : led<=4'b0000;
            2'b10   : led<=4'b1111;
            2'b11   : led<=4'b0000;
            default : led<=4'b0000;
        endcase
    else if (key[3]==0)  //按键4按下时,LED全亮
        led<=4'b1111;
    else
        led<=4'b0000;    //无按键按下时,LED熄灭   
end
endmodule

经程序的下载测试,其演示功能与分析结论完全一致。
演示效果:
分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条