[FPGA]PWM输出

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

发表评论

邮箱地址不会被公开。 必填项已用*标注