在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 464|回复: 3

[求助] 寻找跨时钟域代码bug(verilog)

[复制链接]
发表于 2024-10-29 17:16:44 | 显示全部楼层 |阅读模式
200资产
本帖最后由 weizhl08 于 2024-10-29 17:35 编辑

最近在做一个AD9365芯片的项目:此代码可能存在bug,奈何我怎么也找不出来,只能悬赏啦,希望有高人指出,万分感谢
完成的功能:接收9365的数据,将数据从15.36MHz时钟跨时钟域到122.88MHz,并输出数据使能以及real/imag


输入时序/输出时序在最下面的图里面

代码粘贴在附件

或者我直接粘在下面吧:


module ad_rx_if
(
input           i_clk        ,
input           i_rst_n      ,
input           i_rx_frame   ,
input           i_rx_clk     ,
input   [11:0]  i_rx_data    ,
output  [11:0]  o_rx_real    ,
output  [11:0]  o_rx_imag    ,
output          o_7p68_vld   //
);

reg        r_rx_frame = 1'b0;
reg        r_rx_frame_1d = 1'b0;
reg        r_rx_frame_2d = 1'b0;
reg [11:0] r_rx_data = 12'd0;
reg [11:0] r_rx_data_1d = 12'd0;
reg [11:0] r_rx_data_2d = 12'd0;
reg [11:0] r_rx_clk_real_ping = 1'b0;
reg [11:0] r_rx_clk_imag_ping = 1'b0;
reg [11:0] r_rx_clk_real_pang = 1'b0;
reg [11:0] r_rx_clk_imag_pang = 1'b0;
reg [11:0] r_sys_rx_data = 12'd0;
reg [11:0] r_sys_rx_data_1d = 12'd0;
reg [11:0] r_sys_rx_data_2d = 12'd0;
reg        r_rx_clk_pq_flag = 1'b0;
reg        r_sys_clk_pq_flag = 1'b0;
reg        r_sys_clk_pq_flag_1d = 1'b0;
reg        r_sys_clk_pq_flag_2d = 1'b0;
reg        r_sys_clk_pq_flag_3d = 1'b0;
reg        r_sys_clk_pq_flag_4d = 1'b0;
reg        r_cdc_pq_flag = 1'b0;
reg        r_cdc_pq_flag_1d = 1'b0;
reg [11:0] r_cdc_real;
reg [11:0] r_cdc_imag;
reg        r_cdc_vld;
reg [11:0] r_real;
reg [11:0] r_imag;
reg        r_vld;

//使用下降沿锁定,0x6配置为0x0
always@(negedge i_rx_clk)
begin
    r_rx_data  <= i_rx_data;
    r_rx_frame <= i_rx_frame;
end

//打2拍,消除亚稳态
//理论是同一个时钟域,但因为片间延时以及走线延时不固定
//需要在FPGA同部消除亚稳态
always@(posedge i_rx_clk)
begin
     r_rx_frame_1d <= r_rx_frame;
     r_rx_frame_2d <= r_rx_frame_1d;
end

always@(posedge i_rx_clk)
begin
     r_rx_data_1d <= r_rx_data;
     r_rx_data_2d <= r_rx_data_1d;
end

//rx_clk ---> sys_clk还是使用ping pang操作,等待寄存器稳定
//不要在寄存器的赋值过程中采样
always@(posedge i_rx_clk or negedge i_rst_n)
    if(~i_rst_n)
        r_rx_clk_pq_flag <= 1'b0;
    else if(~r_rx_frame_2d)
        r_rx_clk_pq_flag <= ~r_rx_clk_pq_flag;
    else
        r_rx_clk_pq_flag <= r_rx_clk_pq_flag;

always@(posedge i_rx_clk or negedge i_rst_n)
    if(~i_rst_n)
       r_rx_clk_real_ping <= 12'd0;
    else if(r_rx_frame_2d && ~r_rx_clk_pq_flag)
       r_rx_clk_real_ping <= r_rx_data_2d;
    else
        r_rx_clk_real_ping <= r_rx_clk_real_ping;

always@(posedge i_rx_clk or negedge i_rst_n)
    if(~i_rst_n)
       r_rx_clk_imag_ping <= 12'd0;
    else if(~r_rx_frame_2d && ~r_rx_clk_pq_flag)
       r_rx_clk_imag_ping <= r_rx_data_2d;
    else
        r_rx_clk_imag_ping <= r_rx_clk_imag_ping;

always@(posedge i_rx_clk or negedge i_rst_n)
    if(~i_rst_n)
       r_rx_clk_real_pang <= 12'd0;
    else if(r_rx_frame_2d && r_rx_clk_pq_flag)
       r_rx_clk_real_pang <= r_rx_data_2d;
    else
        r_rx_clk_real_pang <= r_rx_clk_real_pang;

always@(posedge i_rx_clk or negedge i_rst_n)
    if(~i_rst_n)
       r_rx_clk_imag_pang <= 12'd0;
    else if(~r_rx_frame_2d && r_rx_clk_pq_flag)
       r_rx_clk_imag_pang <= r_rx_data_2d;
    else
       r_rx_clk_imag_pang <= r_rx_clk_imag_pang;


//----------------------------------------
//切换时钟域
//----------------------------------------
//理论2拍就可以,但为了预留给rx_clk_real/imag更多保持时间,最好在
//pq的中间采样
always@(posedge i_clk or negedge i_rst_n)
    if(~i_rst_n)
        begin
            r_sys_clk_pq_flag    <= 1'b0;
            r_sys_clk_pq_flag_1d <= 1'b0;
            r_sys_clk_pq_flag_2d <= 1'b0;
            r_sys_clk_pq_flag_3d <= 1'b0;
            r_sys_clk_pq_flag_4d <= 1'b0;
        end
    else
        begin
            r_sys_clk_pq_flag    <= r_rx_clk_pq_flag;
            r_sys_clk_pq_flag_1d <= r_sys_clk_pq_flag   ;
            r_sys_clk_pq_flag_2d <= r_sys_clk_pq_flag_1d;
            r_sys_clk_pq_flag_3d <= r_sys_clk_pq_flag_2d;
            r_sys_clk_pq_flag_4d <= r_sys_clk_pq_flag_3d;
        end

always@(posedge i_clk or negedge i_rst_n)
    if(~i_rst_n)
        r_cdc_pq_flag <= 1'b0;
    else if(r_sys_clk_pq_flag_3d == r_sys_clk_pq_flag_4d)
        r_cdc_pq_flag <= r_sys_clk_pq_flag_4d;
    else
        r_cdc_pq_flag <= r_cdc_pq_flag;

always@(posedge i_clk or negedge i_rst_n)
    if(~i_rst_n)
        begin
            r_cdc_real <= 12'd0;
            r_cdc_imag <= 12'd0;
        end
    else if(r_cdc_pq_flag)//rd ping
        begin
            r_cdc_real <= r_rx_clk_real_ping;
            r_cdc_imag <= r_rx_clk_imag_ping;
        end
    else //rd pang
        begin
            r_cdc_real <= r_rx_clk_real_pang;
            r_cdc_imag <= r_rx_clk_imag_pang;
        end

always@(posedge i_clk or negedge i_rst_n)
    if(~i_rst_n)
        r_cdc_pq_flag_1d <= 1'b0;
    else
        r_cdc_pq_flag_1d <= r_cdc_pq_flag;

always@(posedge i_clk or negedge i_rst_n)
    if(~i_rst_n)
        r_cdc_vld <= 1'b0;
    else if(r_cdc_pq_flag != r_cdc_pq_flag_1d)
        r_cdc_vld <= 1'b1;
    else
        r_cdc_vld <= 1'b0;

//output
always@(posedge i_clk or negedge i_rst_n)
    if(~i_rst_n)
        begin
            r_vld  <= 1'b0;
            r_real <= 12'd0;
            r_imag <= 12'd0;
        end
    else
        begin
            r_vld  <= r_cdc_vld;
            r_real <= r_cdc_real;
            r_imag <= r_cdc_imag;
        end

assign o_rx_real    = r_real;
assign o_rx_imag    = r_imag;
assign o_7p68_vld   = r_vld;

endmodule



9365的输入时序

9365的输入时序

输出时序

输出时序

ad_rx_if.7z

1.13 KB, 下载次数: 6 , 下载积分: 资产 -2 信元, 下载支出 2 信元

跨时钟域代码

发表于 2024-10-29 17:28:30 | 显示全部楼层
spyglass cdc检查一下呢

点评

sdc文件的约束:rx_clk约束到50M,122.88MHz时钟是PLL出来的,应该没问题吧  发表于 2024-10-30 09:14
发表于 2024-10-29 20:26:16 | 显示全部楼层
thanks
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-22 07:46 , Processed in 0.018016 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表