module U_PWM(
input clk,
input rst_n,
input en,
input [31:0] period, // 整个脉冲周期(时钟周期数)
input [31:0] high, // 高电平持续时间(时钟周期数)
output reg out
);
// 状态定义
localparam STATE_IDLE = 2’b00;
localparam STATE_RUN = 2’b01;
localparam STATE_WAIT_END = 2’b10;
reg [1:0] state_c; // 现态
reg [1:0] state_n; // 次态
reg [31:0] cnt; // 周期计数器
// 内部控制信号
wire cnt_end; // 当前周期结束标志
// ==========================================
// 周期计数器逻辑:无算术修饰,防锁死设计
// ==========================================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 32'd0;
end else if (state_c == STATE_RUN || state_c == STATE_WAIT_END) begin
if (cnt_end)
cnt <= 32'd0;
else
cnt <= cnt + 1'b1;
end else begin
cnt <= 32'd0;
end
end
// 安全复位边界:采用 >= 判断,防止动态改小 period 时计数器冲过头导致锁死
assign cnt_end = (state_c == STATE_RUN || state_c == STATE_WAIT_END) && (cnt >= period – 1’b1);
// ==========================================
// 三段式状态机 – 第一段:同步时序逻辑,状态转移
// ==========================================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_c <= STATE_IDLE;
end else begin
state_c <= state_n;
end
end
// ==========================================
// 三段式状态机 - 第二段:组合逻辑,判断状态转移条件
// ==========================================
always @(*) begin
case (state_c)
STATE_IDLE: begin
if (en)
state_n = STATE_RUN;
else
state_n = STATE_IDLE;
end
STATE_RUN: begin
if (!en && cnt_end)
state_n = STATE_IDLE; // 若 en 结束且刚好当前周期完成,直接回 IDLE
else if (!en)
state_n = STATE_WAIT_END; // 若 en 结束但周期未完,进入等待状态
else
state_n = STATE_RUN;
end
STATE_WAIT_END: begin
if (cnt_end)
state_n = STATE_IDLE; // 当前周期结束后,安全返回 IDLE
else
state_n = STATE_WAIT_END; // 周期未结束,继续维持输出
end
default: state_n = STATE_IDLE;
endcase
end
// ==========================================
// 三段式状态机 - 第三段:高性能时序输出判断
// ==========================================
// 核心优化:直接比较 cnt 和 high,消灭所有乘除法和移位
// 为了极致抗干扰,在比较前对 high 信号进行打拍同步(Pipeline)
reg [31:0] high_reg;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
high_reg <= 32'd0;
end else begin
high_reg <= high; // 锁存输入输入,缩短外部布线到内部比较器的关键路径
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
out <= 1'b0;
end else begin
case (state_c) // 配合 high_reg 寄存器延迟,切回现态判断以确保严格的时间对齐
STATE_IDLE: begin
out <= 1'b0;
end
STATE_RUN, STATE_WAIT_END: begin
// 仅剩一个 32 位的基础纯数字量比较器,门延迟极低
if (cnt < high_reg) begin
out <= 1'b1;
end else begin
out <= 1'b0;
end
end
default: out <= 1'b0;
endcase
end
end
endmodule
