always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin //系统复位时,给两个寄存器赋值
key_reg <= 1'b1;
delay_cnt <= 32'd0;
end
else begin
key_reg <= key;//
if(key_reg != key) //一旦检测到按键状态发生变化(有按键被按下或释放)
delay_cnt <= 32'd1000000; //给延时计数器重新装载初始值(计数时间为20ms)
else if(key_reg == key) begin //在按键状态稳定时,计数器递减,开始20ms倒计时
if(delay_cnt > 32'd0)
delay_cnt <= delay_cnt - 1'b1;
else
delay_cnt <= delay_cnt;
end
end
end
别的都好理解,单独抽出延时计时器这块。
key_reg <= key;//????????
if(key_reg != key) //一旦检测到按键状态发生变化(有按键被按下或释放)
delay_cnt <= 32'd1000000; //给延时计数器重新装载初始值(计数时间为20ms)
else if(key_reg == key) begin //在按键状态稳定时,计数器递减,开始20ms倒计时
if(delay_cnt > 32'd0)
delay_cnt <= delay_cnt - 1'b1;
else
delay_cnt <= delay_cnt;
end
写java和c多后 这块挺难理解。我的猜测是always块中的程序是顺序执行的, if(key_reg != key) 这条判断语句(事实上对应的判断电路)和上一句 key_reg <= key;(给寄存器赋值)事实上是有延时的,即电信号从一个节点传递到下一个节点的速度是小于信号的变化速度的(这个几乎是肯定的,内部电容作用)
在此记下我的猜想,日后验证之。
更:这个问题我在夏宇闻老师的书中找到了答案,其实是由于非阻塞赋值产生的,
(1).非阻塞(Non_Blocking)赋值方式( 如 b <= a; )
- 块结束后才完成赋值操作。
- b的值并不是立刻就改变的。
- 这是一种比较常用的赋值方法。(特别在编写可综合模块时)
b <= a;
这种方式的赋值并不是马上执行的,也就是说"always"块内的下一条语句执行后,b并不等于a,而是
保持原来的值。"always"块结束后,才进行赋值。
always @( posedge clk )
begin
b<=a;
c<=b;
end
电路如图:
而阻塞赋值:`always @(posedge clk)
begin
b=a;
c=b;
end
`
这也就解释了下述代码为什么会有如下时序
assign touch_en = (~touch_key_d1) & touch_key_d0;
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0) begin
touch_key_d0 <= 1'b0;
touch_key_d1 <= 1'b0;
end
else begin
touch_key_d0 <= touch_key;
touch_key_d1 <= touch_key_d0;
end
end