图中48行为什么加了k&&后 add_cnt输出变0了(k是1)
`timescale 1ns / 1ps
module top_key_beep(
input sys_clk, //时钟信号 50Mhz
input sys_rst_n, //复位信号
input[1:0] key, //按键信号
output beep //蜂鸣器控制信号
);
//wire define
wire key_value0;
wire key_flag0;
wire key_value1;
wire key_flag1;
//*****************************************************
//** main code
//*****************************************************
//例化按键消抖模块
key_debounce u_key_debounce(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key (key[0]),
.key_flag0 (key_flag0),
.key_value0 (key_value0)
);
key_debounce2 u_key_debounce2(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key1 (key[1]),
.key_flag1 (key_flag1),
.key_value1 (key_value1)
);
//例化蜂鸣器控制模块
beep_control u_beep_control(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key_flag0 (key_flag0),
.key_value0 (key_value0),
.key_flag1 (key_flag1),
.key_value1 (key_value1),
.beep (beep)
);
endmodule
module key_debounce(
input sys_clk, //外部 50M 时钟
input sys_rst_n, //外部复位信号,低有效
input key, //外部按键输入
output reg key_flag0, //按键数据有效信号
output reg key_value0, //按键消抖后的数据
output reg k
);
//reg define
reg [31:0] delay_cnt;
reg[1:0] key_reg;
//*****************************************************
//** main code
//*****************************************************
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
key_reg[0] <= 1'b1;
delay_cnt <= 32'd0;
end
else begin
key_reg[0] <= key;
if(key_reg[0] != key) //一旦检测到按键状态发生变化(有按键被按下或释放)
delay_cnt <= 32'd1000000; //给延时计数器重新装载初始值(计数时间为 20ms)
//delay_cnt <= 32'd4; //仅用仿真
else if(key_reg[0] == key) begin //在按键状态稳定时,计数器递减,开始 20ms 倒计时
if(delay_cnt > 32'd0)
delay_cnt <= delay_cnt - 1'b1;
else
delay_cnt <= delay_cnt;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
key_flag0 <= 1'b0;
key_value0 <= 1'b1;
k<= 1'b0;
end
else begin
if(delay_cnt == 32'd1) begin //当计数器递减到 1 时,说明按键稳定状态维持了 20ms
key_flag0 <= 1'b1; //此时消抖过程结束,给出一个时钟周期的标志信号
key_value0 <= key; //并寄存此时按键的值
// k<= ~k;
k<=1'b1;
end
else begin
key_flag0 <= 1'b0;
key_value0<= key_value0;
k<=k;
end
end
end
endmodule
module key_debounce2(
input sys_clk, //外部 50M 时钟
input sys_rst_n, //外部复位信号,低有效
input key1, //外部按键输入
output reg key_flag1, //按键数据有效信号
output reg key_value1 //按键消抖后的数据
);
//reg define
reg [31:0] delay_cnt;
reg[1:0] key_reg;
//*****************************************************
//** main code
//*****************************************************
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
key_reg[1] <= 1'b1;
delay_cnt <= 32'd0;
end
else begin
key_reg[1] <= key1;
if(key_reg[1] != key1) //一旦检测到按键状态发生变化(有按键被按下或释放)
delay_cnt <= 32'd1000000; //给延时计数器重新装载初始值(计数时间为 20ms)
//delay_cnt <= 32'd4; //仅用仿真
else if(key_reg[1] == key1) begin //在按键状态稳定时,计数器递减,开始 20ms 倒计时
if(delay_cnt > 32'd0)
delay_cnt <= delay_cnt - 1'b1;
else
delay_cnt <= delay_cnt;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
key_flag1 <= 1'b0;
key_value1<= 1'b1;
end
else begin
if(delay_cnt == 32'd1) begin //当计数器递减到 1 时,说明按键稳定状态维持了 20ms
key_flag1 <= 1'b1; //此时消抖过程结束,给出一个时钟周期的标志信号
key_value1 <= key1; //并寄存此时按键的值
end
else begin
key_flag1 <= 1'b0;
key_value1<= key_value1;
end
end
end
endmodule
module beep_control(
//input
input sys_clk, //系统时钟
input sys_rst_n, //复位信号,低电平有效
input key_flag0, //按键有效信号
input key_value0, //消抖后的按键信号
input key_flag1, //按键有效信号
input key_value1, //消抖后的按键信号
input k,
output reg beep //蜂鸣器控制信号
);
parameter TIM1_PWM = 2_400_000;
parameter TIM1_100MS = 4_000_000;
reg [21:0] cnt;
wire add_cnt;
wire end_cnt;
//*****************************************************
//** main code
//*****************************************************
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
beep <= 1'b0;
else if(key_flag0 && (~key_value0)) //判断按键是否有效按下
beep <= ~beep;
// else if(k==1'b1 &&( add_cnt && cnt ==TIM1_PWM-1))
else if( add_cnt && cnt ==TIM1_PWM-1)
beep<= 1'b1;
else if(end_cnt)
beep<= 1'b0;
else if(k==1'b1 && !add_cnt)
beep<= 1'b1;
end
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt<=0;
else if(add_cnt)begin
if(end_cnt)
cnt<=0;
else
cnt<=cnt + 1;
end
end
assign add_cnt = k && (~key_value1);
//assign add_cnt = ~key_value1;
assign end_cnt = add_cnt && cnt == TIM1_100MS-1;
endmodule
以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:
首先,关于加了 k&& 后 add_cnt 输出变 0 的问题,是因为当 k=1 时,只有 key_value1=0 才能使 add_cnt=1,否则 add_cnt=0,所以在这种情况下,add_cnt 会一直为 0。
至于按下 key1 松手后的问题,可能是因为没有对计数器进行清零,导致松手后计数器仍在继续计数,进而影响占空比的改变。
以下是修改后的代码,包括对 add_cnt 的修改和对计数器的清零:
module beep_control(
//input
input sys_clk, //系统时钟
input sys_rst_n, //复位信号,低电平有效
input key_flag0, //按键有效信号
input key_value0, //消抖后的按键信号
input key_flag1, //按键有效信号
input key_value1, //消抖后的按键信号
output reg beep //蜂鸣器控制信号
);
parameter TIM1_PWM = 2_400_000;
parameter TIM1_100MS = 4_000_000;
reg [21:0] cnt;
wire add_cnt;
wire end_cnt;
reg last_k;
reg last_key_value1;
reg [21:0] duty_cnt;
//*****************************************************
//** main code
//*****************************************************
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
beep <= 1'b0;
duty_cnt <= 22'h0;
last_k <= 1'b0;
last_key_value1 <= 1'b0;
end
else begin
if (key_flag0 && (~key_value0)) //判断按键是否有效按下
beep <= ~beep;
else if (k && ~last_k && add_cnt) begin
duty_cnt <= duty_cnt + 1;
if (duty_cnt >= TIM1_100MS) begin
duty_cnt <= 0;
beep <= ~beep;
end
end
last_k <= k;
if (key_value1 != last_key_value1) begin
last_key_value1 <= key_value1;
if (key_value1 == 1'b1)
duty_cnt <= 0;
end
end
end
assign add_cnt = k && (~key_value1);
assign end_cnt = add_cnt && (cnt == TIM1_100MS-1);
always @ (posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
cnt <= 0;
else if (add_cnt) begin
if (end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
else
cnt <= 0;
end
endmodule
其中加入了一个 duty_cnt 计数器,用于计算每个占空比的时间,并在达到对应时间时改变蜂鸣器的状态。
同时,还加入了一个 last_key_value1 记录上一次 key_value1 的值,用于检测 key_value1 的变化并清空计数器。