问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Verilog跨时钟域处理之脉冲同步电路详解

创作时间:
作者:
@小白创作中心

Verilog跨时钟域处理之脉冲同步电路详解

引用
CSDN
1.
https://m.blog.csdn.net/galaxyerkw/article/details/127619676

在数字电路设计中,跨时钟域处理是一个常见的挑战。本文将详细介绍如何使用Verilog实现脉冲同步电路,该电路能够将一个时钟域的脉冲信号准确地转换到另一个时钟域。

跨时钟域处理的概念

在数字电路设计中,跨时钟域处理是一个常见的挑战。当两个时钟域需要进行数据传输时,必须确保数据在目标时钟域中能够正确地被采样和处理。本文将详细介绍如何使用Verilog实现脉冲同步电路,该电路能够将一个时钟域的脉冲信号准确地转换到另一个时钟域。

脉冲同步电路的概念和框架

从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
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号