推荐答案
测试一下
题目
4.7 时钟切换方法
参考答案与知识点
参考答案
普通时钟切换直接使用组合逻辑MUX实现,例如 assign clk_o = sel ? clkb : clka; 这种方式电路简单、成本低,但切换瞬间可能产生毛刺(窄脉冲),因为sel可能不在时钟的稳定电平期间变化。适用于切换时下游模块处于复位或非工作状态的场景。
去毛刺无缝切换需要避免毛刺,通常采用时钟下降沿采样选通信号,确保在时钟低电平时切换。经典电路:对每个时钟域分别用两个触发器同步sel,并利用反馈生成使能信号。具体实现时,先用sel的上升沿(或电平)在clka域产生一个使能信号en_a,再用clka的下降沿打拍,输出控制clka的与门;类似地产生en_b并同步到clkb域。最后将两个与门输出相或得到clk_o。例如:
module glitch_free_mux (
input clka, clkb, rst_n, sel,
output clk_o
);
reg sel_a_ff1, sel_a_ff2;
reg sel_b_ff1, sel_b_ff2;
wire en_a, en_b;
always @(posedge clka or negedge rst_n) begin
if (!rst_n) sel_a_ff1 <= 0;
else sel_a_ff1 <= ~sel & sel_b_ff2; // 反相使能
end
always @(negedge clka or negedge rst_n) begin
if (!rst_n) sel_a_ff2 <= 0;
else sel_a_ff2 <= sel_a_ff1;
end
always @(posedge clkb or negedge rst_n) begin
if (!rst_n) sel_b_ff1 <= 0;
else sel_b_ff1 <= sel & sel_a_ff2;
end
always @(negedge clkb or negedge rst_n) begin
if (!rst_n) sel_b_ff2 <= 0;
else sel_b_ff2 <= sel_b_ff1;
end
assign en_a = sel_a_ff2;
assign en_b = sel_b_ff2;
assign clk_o = (en_a & clka) | (en_b & clkb);
endmodule
该电路利用下降沿采样避免在时钟上升沿附近切换,确保切换发生在时钟低电平期间,从而消除毛刺。注意sel需要与时钟异步,需用双触发器同步避免亚稳态。此方法广泛应用于多时钟域系统中,如芯片复位后初始切换,或者动态时钟切换场景。
涉及知识点
- 时钟切换电路设计
- 毛刺产生机理与消除
- 双触发器同步器
- 下降沿采样与使能反馈
- 多时钟域异步信号处理