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


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

    例: 

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

       程序:

        

     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} <=  3'd0;
        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(8'h55);
                
          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} <=  3'd0;
        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} <= 3'd0;
            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

     仿真程序同上。

    仿真图:

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

  • 相关阅读:
    反射入门
    把数据库表的信息添加到list集合里面
    简单的事务分析及使用
    java-web与jdbc 的使用
    菜鸟入门bootstrap
    如何彻底的卸载mysql
    发生系统错误 1067,解决方案
    纯js的购物车案例
    idea里面怎么把自己项目添加maven
    js入门
  • 原文地址:https://www.cnblogs.com/fhyfhy/p/4417063.html
Copyright © 2020-2023  润新知