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的输入时序
输出时序
ad_rx_if.7z
1.13 KB, 下载次数: 6
, 下载积分:
资产 -2 信元, 下载支出 2 信元
跨时钟域代码