一:背景介绍:
本篇文章是对昨天程序的一个再使用,关于LED的循环移动,我有话说,其他的就没什么要说的了。
循环左移有两种方法:
一个是:左移运算符 <<;还有一种是:Verilog描述语言特有的拼接符号{ } ;
我个人推荐 拼接符号,简约,快捷,清晰明朗。
二:程序
//======================================//
//==Fosc : 50MHz
//==Timescale : 1ns/1ns
//==File name : huxideng.v
//==Date : 2016-09-30
//==Author : CY
//==Function : 每按键一次,则 led灯左移一位变亮,每次仅有一个LED灯亮
//==Description:
// 当没有按键 按下时,flag_10ms=1'b0;
// 当有 按键 按下时,flag_10ms=1'b1;
//
//======================================//
module key_new(
input wire sclk,
input wire rst_n,
input wire key_in,
output reg [3:0] LED_out
);
//==========================//
parameter T_10ms=19'd499_999;
//==========================//
reg [18:0] cnt_10ms;
reg flag_10ms;
reg key_value;
//==========cnt_10ms==========//
always@(posedge sclk or negedge rst_n)
if(!rst_n)
cnt_10ms <=19'd0;
else if(key_in==1'b1) //没有这一句,意味着是可以累积计数的,如此会出现,即使遇到1就停止计数,一旦监测到0就会累加计数;
cnt_10ms <=19'd0; //我们实际需要的是:key_in=1时,清零,遇到0时就累积加,所以,必须要添加此句
else if(cnt_10ms==T_10ms) //为的是cnt_10ms>T_10ms,如此就不会执行 cnt_10ms <=cnt_10ms+1'b1;
cnt_10ms <=19'd500_000;
// else if(key_in==1'b0) //
else if(key_in==1'b0&&cnt_10ms<=T_10ms) //目的 是:计数T_10ms+1'b1之后,就不加1
cnt_10ms <=cnt_10ms+1'b1;
//==========flag_10ms========//
always@(posedge sclk or negedge rst_n)
if(!rst_n)
flag_10ms <=1'b0; //因为key_value要取反,所以光有flag_10ms=0是不行的,还需要key_in==1'b0;按下了才有效果
else if(cnt_10ms==T_10ms-1'b1)
flag_10ms <=1'b1;
else
flag_10ms <=1'b0;
//==================//
always@(posedge sclk or negedge rst_n)
if(!rst_n)
key_value <=1'b0; //我看到是LED上电就亮,我还就奇怪了,不可能的啊!后来看看电路图,
// else if(flag_10ms==1'b1) //原来LED是高电平亮,我的初始化key_value<=1'b1;
else if(flag_10ms==1'b1&&key_in==1'b0)//所以不管怎么修改电路,都是LED开机就亮,修正为0时,就可以 了
key_value <=1'b1;
else
key_value <=1'b0;
always@(posedge sclk or negedge rst_n)
if(!rst_n)
LED_out <=4'b0001;
else if(key_value==1'b1)
LED_out <= {LED_out[2:0],LED_out[3]};
endmodule