跨时钟域数据同步

来源:互联网 发布:持有期收益率知乎 编辑:程序博客网 时间:2024/06/02 06:53

   在一些较复杂的逻辑设计中,通常会涉及到多个时钟域,在跨时钟域设计时,要保证数据同步,可采用如下策略使得设计满足时序要求:

(1) 采用双端口RAM或异步时钟FIFO

(2) 利用多级寄存器缓存数据

      最近在做数据采集模块时,关于trig_in信号的处理就是这样处理的。trig_in是一个脉冲信号,由DDS模块产生,在DDS模块中,每个信号周期的起始都会产生一个周期同步脉冲,也就是trig_in,DDS模块采用的是50MHz时钟,产生信号的周期大概100Hz~600Hz。当trig_in脉冲信号到来时,数据采集模块要记录此时trig_in对应的AD采样数据在一帧数据(1020个采样点数据)中的位置。AD采样时钟是50MHz,DMA时钟是150MHz,采用两级FIFO结构,前一级存储AD采样点,后一级缓存前一级数据,并添加帧信息。为保证数据同步:在50M时钟下,先将trig信息缓存到reg变量trig_position中,然后在150M时钟下,将trig_position锁存到trig_channel_reg寄存器中,之后在150M时钟下将trig_channel_reg锁存到trig_channel_info,最后在150M时钟下将trig_channel_info写入到第二级FIFO中。主要代码如下:

    //========== trig_position ==========            always @(posedge ad_clk) begin      trig_reg1 <= trig_in;  // trig_in是边沿信号      trig_reg2 <= trig_reg1;    end    assign trigger = trig_reg1 & (!trig_reg2);        always @(posedge ad_clk) begin // trig_in是边沿信号      if(trigger == 1) begin        trig_position <= wr_fifo1_count + 1; //trig_position        trig_flag <= 8'd255;        trig_latch_en <= 1'b1;      end       else if(wr_fifo1_count == 10'd1020) begin //1个packet有1024个字,包含1020个采样点数据        trig_position <= 0; //wr_fifo2_count = 1022时,将trig_position写入fifo中        trig_flag <= 0;        trig_latch_en <= 1'b0;      end      else begin        trig_position <= trig_position;        trig_flag <= trig_flag;      end    end     // ========== trig_channel_info ==========    always @(posedge dma_clk) begin //跨时钟域锁存数据      if(!rst_n) trig_channel_reg <= 32'd0;      else if(trig_latch_en == 1'b1) trig_channel_reg <= {CHANNEL_NUM,trig_flag,trig_position};      else trig_channel_reg <= ({{CHANNEL_NUM},24'd0});      end              always @(posedge dma_clk) begin      if(!rst_n) trig_channel_info <= 32'd0;      else if(wr_fifo1_count == 10'd1020) trig_channel_info <= trig_channel_reg;      else trig_channel_info <= trig_channel_info;    end    always @(posedge dma_clk) begin      if(!rst_n) fifo2_din_reg <= 0;      else case(wr_fifo2_count)        11'd1020: fifo2_din_reg <= block_num;        11'd1021: fifo2_din_reg <= trig_channel_info;        11'd1022: fifo2_din_reg <= crc_code;        11'd1023: fifo2_din_reg <= reserve_register;        default: fifo2_din_reg <= sample_data;      endcase    end



0 0
原创粉丝点击