FPGA中跨异步时钟处理的方法,是面试中经常碰到的问题,也是我们平时工作中经常会碰到的场景,对于单bit的跨异步时钟处理,我们最常用的方法就是打两拍,但这时这两级寄存器最好是放到同一个Slice中,比如下面的代码:
代码语言:javascript复制reg reg_1;
reg reg_2, reg_3;
always @ ( posedge clk_src ) begin
reg_1 <= ~reg_1;
end
always @ ( posedge clk_dst) begin
reg_2 <= reg_1;
reg_3 <= reg_2;
end
reg_2
和reg_3
应该放到同一个Slice中,但综合工具并不是那么智能,有时并不会综合到同一个Slice中,这时就需要我们添加ASYNC_REG
的属性:
(*ASYNC_REG="true"*)reg reg_2, reg_3;
其实Vivado中还提供了另外一种处理单bit跨时钟的方式,就是xpm_cdc_single
对于上面的跨时钟域场景,我们可以采用如下方式例化:
代码语言:javascript复制 xpm_cdc_single #(
.DEST_SYNC_FF(2), // DECIMAL; range: 2-10
.INIT_SYNC_FF(0), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
.SRC_INPUT_REG(1) // DECIMAL; 0=do not register input, 1=register input
)
xpm_cdc_single_inst (
.dest_out(reg_3), // 1-bit output: src_in synchronized to the destination clock domain. This output is
// registered.
.dest_clk(clk_dst), // 1-bit input: Clock signal for the destination clock domain.
.src_clk(clk_src), // 1-bit input: optional; required when SRC_INPUT_REG = 1
.src_in(reg_1) // 1-bit input: Input signal to be synchronized to dest_clk domain.
);
xpm_cdc_single
的原语,会自动插入ASYNC_REG
属性,保证放到同一个Slice中。