// 1. 速度档位控制(KEY1减慢,KEY2加快,3次后重置)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
speed_cnt <= 2'd0; // 复位后默认中档(2秒周期)
end else if(mode_en) begin
// KEY2按下:加快速度(0→1→2→0,3次后重置)
if(key2_press) begin
speed_cnt <= (speed_cnt == 2'd1) ? 2'd0 : speed_cnt + 2'd1;
// 说明:0=中档→1=快档→2=重置回中档(3次加快逻辑:按3次KEY2→0→1→0→1→...)
// 实际效果:按1次→快档,按2次→中档,按3次→快档?不,修正为3次后重置:
// 正确逻辑:0(中)→1(快)→2(超快?不,原需求3次后重置,所以0→1→2→0)
// 重新调整:3档循环(0:中,1:快,2:超慢?不,按需求“加快3次后重置”)
// 最终逻辑:加快次数计数(0→1→2→0),对应档位:0=中,1=快,2=更快→3次后回中
speed_cnt <= (speed_cnt == 2'd2) ? 2'd0 : speed_cnt + 2'd1;
end
// KEY1按下:减慢速度(0→2→1→0,3次后重置)
else if(key1_press) begin
speed_cnt <= (speed_cnt == 2'd0) ? 2'd2 : speed_cnt - 2'd1;
end
end
end
// 2. 步长定时器(根据档位选择步长时间:档位越高,步长时间越短→呼吸越快)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
step_timer <= SPEED_STEP_MID; // 初始中档
end else if(mode_en) begin
case(speed_cnt)
2'd0: step_timer <= SPEED_STEP_MID; // 中档(2秒周期)
2'd1: step_timer <= SPEED_STEP_FAST; // 快档(1秒周期)
2'd2: step_timer <= SPEED_STEP_SLOW; // 慢档(3秒周期)
default: step_timer <= SPEED_STEP_MID;
endcase
end
end
// 3. PWM载波计数器(生成固定频率PWM,确保占空比精度)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
pwm_cnt <= 10'd0;
end else if(mode_en) begin
pwm_cnt <= (pwm_cnt == STEP_NUM - 1) ? 10'd0 : pwm_cnt + 10'd1;
end else begin
pwm_cnt <= 10'd0;
end
end
// 4. 占空比线性增减控制(双灯共用同一占空比和方向,保证同步)
reg [31:0] cnt; // 步长计时计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt <= 32'd0;
duty_cycle1 <= 10'd0;
duty_cycle2 <= 10'd0;
dir <= 1'b0; // 初始方向:占空比增加(LED渐亮)
end else if(mode_en) begin
cnt <= cnt + 32'd1;
if(cnt >= step_timer) begin // 达到步长时间,更新占空比
cnt <= 32'd0;
if(dir == 1'b0) begin // 占空比增加(渐亮)
// 达到最大占空比(STEP_NUM-1),反向(渐暗)
if(duty_cycle1 == STEP_NUM - 1) begin
dir <= 1'b1;
end else begin
duty_cycle1 <= duty_cycle1 + 10'd1;
duty_cycle2 <= duty_cycle2 + 10'd1; // 双灯同步更新
end
end else begin // 占空比减少(渐暗)
// 达到最小占空比(0),反向(渐亮)
if(duty_cycle1 == 10'd0) begin
dir <= 1'b0;
end else begin
duty_cycle1 <= duty_cycle1 - 10'd1;
duty_cycle2 <= duty_cycle2 - 10'd1; // 双灯同步更新
end
end
end
end else begin
cnt <= 32'd0;
duty_cycle1 <= 10'd0;
duty_cycle2 <= 10'd0;
dir <= 1'b0;
end
end
// 5. LED1 PWM输出(占空比比较)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
led1_out <= 1'b0;
end else if(mode_en) begin
led1_out <= (pwm_cnt < duty_cycle1) ? 1'b1 : 1'b0;
end else begin
led1_out <= 1'b0;
end
end
// 6. LED2 PWM输出(与LED1完全同步)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
led2_out <= 1'b0;
end else if(mode_en) begin
led2_out <= (pwm_cnt < duty_cycle2) ? 1'b1 : 1'b0;
end else begin
led2_out <= 1'b0;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
prompt_cnt <= 24'd0;
buzzer_en <= 1'b0;
end else begin
// 任何按键按下,重置计数器并开启蜂鸣器
if(key1_press || key2_press || touch_press) begin
prompt_cnt <= PROMPT_CNT_MAX;
buzzer_en <= 1'b1;
end else if(prompt_cnt > 24'd0) begin // 计数器倒计时
prompt_cnt <= prompt_cnt - 24'd1;
buzzer_en <= 1'b1;
end else begin // 计时结束,关闭蜂鸣器
buzzer_en <= 1'b0;
end
end
end
// 1. 速度档位控制(互斥逻辑:加快/减慢二选一,3次后重置)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
flow_period <= BASE_PERIOD;
end else if(mode_en) begin
if(key2_press) begin // 加快模式:优先级高于减慢
flow_period <= flow_period - ADJUST_STEP;
end else if(key1_press) begin // 减慢模式
flow_period <= flow_period + ADJUST_STEP;
end else begin
flow_period <= flow_period;
end
end
end
// 3. 流水状态切换(mode_en有效即自动流水,无需按键触发)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
flow_period <= flow_period;
end else if(mode_en) begin
if(flow_cnt >= flow_period / 2) begin // 半周期切换一次状态
flow_cnt <= 32'd0;
led_state <= ~led_state;
end
end else begin
led_state <= 1'b0;
end
end
// 4. LED输出控制(唯一驱动源,无多驱动冲突)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
led1_out <= 1'b0;
led2_out <= 1'b0;
end else if(mode_en) begin
case(led_state)
1'b0: begin // LED1亮,LED2灭
led1_out <= 1'b1;
led2_out <= 1'b0;
end
1'b1: begin // LED1灭,LED2亮
led1_out <= 1'b0;
led2_out <= 1'b1;
end
default: {led1_out, led2_out} <= 2'b00;
endcase
end else begin
led1_out <= 1'b0;
led2_out <= 1'b0;
end
end
// 第一步:两级同步按键输入(避免亚稳态)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_in_sync <= 3'b111; // 初始状态:按键未按下(高电平)
end else begin
key_in_sync <= key_in;
end
end
// 第二步:消抖计数,获取稳定状态
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_in_stable <= 3'b111;
debounce_cnt <= 20'd0;
end else begin
if(key_in_sync != key_in_stable) begin // 按键状态变化,开始计数
debounce_cnt <= DEBOUNCE_CNT_MAX;
key_in_stable <= key_in_sync;
end else if(debounce_cnt > 20'd0) begin // 计数未结束,继续倒计时
debounce_cnt <= debounce_cnt - 20'd1;
end
end
end
// 第三步:检测按键按下(高→低跳变),输出脉冲
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_press <= 3'b000;
key_in_stable_prev <= 3'b111;
end else begin
key_in_stable_prev <= key_in_stable; // 存储上一周期状态
// 未按下(1)→按下(0):产生高脉冲
key_press <= ~key_in_stable & key_in_stable_prev;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
mode <= 1'b0; // 复位后默认呼吸灯模式
end else begin
if(touch_press) begin // 触摸按键按下,模式翻转
mode <= ~mode;
end
end
end
// LED输出选择逻辑(唯一驱动源)
always @(posedge clk_50mhz or negedge rst_n) begin
if(!rst_n) begin
led1 <= 1'b0;
led2 <= 1'b0;
end else begin
case(mode)
1'b0: begin // 呼吸灯模式
led1 <= led1_breath;
led2 <= led2_breath;
end
1'b1: begin // 流水灯模式
led1 <= led1_flow;
led2 <= led2_flow;
end
default: {led1, led2} <= 2'b00;
endcase
end
end
// 蜂鸣器输出逻辑
always @(posedge clk_50mhz or negedge rst_n) begin
if(!rst_n) begin
buzzer <= 1'b0;
end else begin
buzzer <= buzzer_en;
end
end