码迷,mamicode.com
首页 > 其他好文 > 详细

取时钟线的下降沿时的数据错位问题解决

时间:2015-04-11 10:16:38      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

   在项目中,涉及到不同时钟域通信的时候,往往要在时钟边沿时刻取数据线的值,但是如果数据线上的数据持续时间比较短,取时钟沿之后将无法捕捉到数据线上的数据,此时读取的数据都是错误的数据。此时可以把数据线上的数据也相应的延迟几个时钟周期,则就可以读到正确的数据。

例: 

 读不到正确的数据的例程:

   程序:

    

技术分享
 module  testedge(
                  clk,
                                    rst_n,
                                    
                                    sclk,
                                    sdat,
                                    
                                    dataout,
                                    flag
                                    );

 input           clk;
 input           rst_n;
 
 input           sclk;
 input           sdat;
 
 output   [7:0]  dataout;
 output          flag;
 reg             flag;
 reg      [7:0]  dataout;
 //-------------------------------------
 /* 取边沿时刻 */
  reg                sclk_1;
    reg                sclk_2;
    reg                sclk_3;
    wire               sclk_pos;
 always @(posedge clk or negedge rst_n)
 begin
  if(!rst_n)
   begin
      {sclk_3,sclk_2,sclk_1} <=  3d0;
    end
  else 
    begin
       {sclk_3,sclk_2,sclk_1} <=  {sclk_2,sclk_1,sclk};
    end
  end
    
    assign sclk_pos = ~sclk_3&sclk_2;
    
    reg   [2:0]  n;
    reg   [2:0]  state;
 always @(posedge clk or negedge rst_n)
 begin
  if(!rst_n)
   begin
      dataout <= 0;
            flag <= 0;
            state <= 0;
            n <= 0;
    end
  else 
    begin
      case(state)
            d0:
              begin
                    if(sclk_pos)
                     begin
                         dataout[n] <= sdat;
                         state <= d1;
                        end
                    end
             d1:
               begin
                        if(n == 7)
                         begin
                             n <= 0;
                             state <= d2;
                            end
                         else 
                             begin
                             n <= n + 1; 
                             state <= d0; 
                             end
                     end
                d2:
                  begin
                        flag <= 1;    
                        state <= d3;    
                     end
                d3:
                  begin
                        flag <= 0;    
                        state <= d0;    
                     end
                default:state <= d0;    
             endcase
    end
  end
    
    
endmodule
View Code

 

  仿真程序:

    发送的数据为8‘h55;

技术分享
/********************************Copyright**************************************                           
**----------------------------File information--------------------------
** File name  :.v  
** CreateDate :2015.
** Funtions   :
** Operate on :M5C06N3L114C7
** Copyright  :All rights reserved. 
** Version    :V1.0
**---------------------------Modify the file information----------------
** Modified by   :
** Modified data :        
** Modify Content:
*******************************************************************************/
 

 module   testedg_tb;
 reg           clk;
 reg           rst_n;
 
 reg           sclk;
 reg           sdat;
 
 wire   [7:0]  dataout;
 wire          flag;

 testedge   testedge_1(
                  .clk,
                                    .rst_n,
                                    
                                    .sclk,
                                    .sdat,
                                    
                                    .dataout,
                                    .flag
                                    );

  parameter  tck = 24;
    parameter  t = 1000/tck;
    always 
        #(t/2) clk = ~clk;
        
        task   send;
        input  [7:0]  datain;
        begin
            #(5*t)    sclk = 0;
            #(2*t)  sdat = datain[0];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[1];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[2];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[3];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[4];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[5];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[6];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = datain[7];
            #(2*t)  sclk = 1; 
            #(2*t)  sclk = 0;
                    sdat = 0;
            end
        endtask
    
    initial 
      begin
        clk = 0;
            rst_n = 0;
            
        sclk = 0;
            sdat = 0;
            
            
            #(6*t)      rst_n = 1;
            
            #(6*t) send(8h55);
            
      end
        
 endmodule
 
View Code

 

  仿真图:

    技术分享

 数据线上加入延时之后可以读到正确的数据:

  程序:

    

技术分享
 module  testedge(
                  clk,
                                    rst_n,
                                    
                                    sclk,
                                    sdat,
                                    
                                    dataout,
                                    flag
                                    );

 input           clk;
 input           rst_n;
 
 input           sclk;
 input           sdat;
 
 output   [7:0]  dataout;
 output          flag;
 reg             flag;
 reg      [7:0]  dataout;
 //-------------------------------------
 /* 取边沿时刻 */
  reg                sclk_1;
    reg                sclk_2;
    reg                sclk_3;
    wire               sclk_pos;
 always @(posedge clk or negedge rst_n)
 begin
  if(!rst_n)
   begin
      {sclk_3,sclk_2,sclk_1} <=  3d0;
    end
  else 
    begin
       {sclk_3,sclk_2,sclk_1} <=  {sclk_2,sclk_1,sclk};
    end
  end
    
    assign sclk_pos = ~sclk_3&sclk_2;
    //----------------------------------------------
      /* 添加部分 */
     reg         sdat_1;
     reg         sdat_2;     
     reg         sdat_3;        
     wire        sdat_flag;
    always @(posedge clk or negedge rst_n)
     begin
      if(!rst_n)
       begin
        {sdat_3,sdat_2,sdat_1} <= 3d0;
        end
      else 
        begin
         {sdat_3,sdat_2,sdat_1} <= {sdat_2,sdat_1,sdat};
        end
      end
    assign     sdat_flag = sdat_3;
        
    //----------------------------------------
    reg   [2:0]  n;
    reg   [2:0]  state;
 always @(posedge clk or negedge rst_n)
 begin
  if(!rst_n)
   begin
      dataout <= 0;
            flag <= 0;
            state <= 0;
            n <= 0;
    end
  else 
    begin
      case(state)
            d0:
              begin
                    if(sclk_pos)
                     begin
                         dataout[n] <= sdat_flag;      /* 修改为延时之后的输入数据 */
                         state <= d1;
                        end
                    end
             d1:
               begin
                        if(n == 7)
                         begin
                             n <= 0;
                             state <= d2;
                            end
                         else 
                             begin
                             n <= n + 1; 
                             state <= d0; 
                             end
                     end
                d2:
                  begin
                        flag <= 1;    
                        state <= d3;    
                     end
                d3:
                  begin
                        flag <= 0;    
                        state <= d0;    
                     end
                default:state <= d0;    
             endcase
    end
  end
    
    
endmodule
View Code

 

 仿真程序同上。

仿真图:

技术分享

  注:并非所有情况都要这么做,视情况而定,而这样做的好处是更严谨。

 

取时钟线的下降沿时的数据错位问题解决

标签:

原文地址:http://www.cnblogs.com/fhyfhy/p/4417063.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!