本帖最后由 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
经程序的下载测试,其演示功能与分析结论完全一致。 演示效果:
|