跨时钟域处理的概念
详见:【Verilog】跨时钟域处理(一)——多bit MUX同步
脉冲同步电路的概念和框架
从A时钟域提取一个单时钟周期宽度脉冲,然后在新的时钟域B建立另一个单时钟宽度的脉冲。
A时钟域的频率是B时钟域的10倍;A时钟域脉冲之间的间隔很大,无需考虑脉冲间隔太小的问题。
电路的接口如下图所示。data_in是脉冲输入信号,data_out是新的脉冲信号;clk_fast是A时钟域时钟信号,clk_slow是B时钟域时钟信号;rst_n是异步复位信号。
脉冲同步电路 解析和代码
本电路设计三个过程:
1. 脉冲输入时,将“脉冲信号转化为电平信号”: 当检测到data_in拉高(持续一周期的脉冲),pulse_sig记录。
//脉冲信号转电平信号,参照快时钟
//检测到一个clk的脉冲,在pulse_sig记录一个1。
reg pulse_sig;
always@(posedge clk_fast or negedge rst_n)
begin
if(!rst_n) pulse_sig <= 0;
else pulse_sig <= (data_in) ? ~pulse_sig : pulse_sig;
end
2. clk_fast向clk_slow切换时,clk_slow打两拍作为缓冲。
//慢时钟打两拍
reg pulse_sig_clap_1;
reg pulse_sig_clap_2;
always@(posedge clk_slow or negedge rst_n)
begin
if(!rst_n) begin
pulse_sig_clap_1 <= 0;
pulse_sig_clap_2 <= 0;
end
else begin
pulse_sig_clap_1 <= pulse_sig;
pulse_sig_clap_2 <= pulse_sig_clap_1;
end
end
3. 输出端还原一次脉冲,即将“电平信号转化为脉冲信号”。
//电平信号转脉冲信号,参照慢时钟
reg pulse_sig_convert; //准备转化为脉冲输出的电平信号
always@(posedge clk_slow or negedge rst_n)
begin
if(!rst_n) pulse_sig_convert <= 0;
else pulse_sig_convert <= pulse_sig_clap_2;
end
/*
如果接收到脉冲,pulse_sig、接下来打两拍的触发器、准备转化的触发器内的值分别为:
100 0->010 0->001 0(输出脉冲)->000 1(输出脉冲)
*/
assign dataout = ( (!pulse_sig_convert && pulse_sig_clap_2) || (pulse_sig_convert && !pulse_sig_clap_2)) ? 1 : 0;
完整代码:
module pulse_detect(
input clk_fast ,
input clk_slow ,
input rst_n ,
input data_in ,
output dataout
);
//脉冲信号转电平信号,参照快时钟
//检测到一个clk的脉冲,在pulse_sig记录一个1。
reg pulse_sig;
always@(posedge clk_fast or negedge rst_n)
begin
if(!rst_n) pulse_sig <= 0;
else pulse_sig <= (data_in) ? ~pulse_sig : pulse_sig;
end
//慢时钟打两拍
reg pulse_sig_clap_1;
reg pulse_sig_clap_2;
always@(posedge clk_slow or negedge rst_n)
begin
if(!rst_n) begin
pulse_sig_clap_1 <= 0;
pulse_sig_clap_2 <= 0;
end
else begin
pulse_sig_clap_1 <= pulse_sig;
pulse_sig_clap_2 <= pulse_sig_clap_1;
end
end
//电平信号转脉冲信号,参照慢时钟
reg pulse_sig_convert; //准备转化为脉冲输出的电平信号
always@(posedge clk_slow or negedge rst_n)
begin
if(!rst_n) pulse_sig_convert <= 0;
else pulse_sig_convert <= pulse_sig_clap_2;
end
/*
如果接收到脉冲,pulse_sig、接下来打两拍的触发器、准备转化的触发器内的值分别为:
100 0->010 0->001 0(输出脉冲)->000 1(输出脉冲)
*/
assign dataout = ( (!pulse_sig_convert && pulse_sig_clap_2) || (pulse_sig_convert && !pulse_sig_clap_2)) ? 1 : 0;
endmodule