zoukankan      html  css  js  c++  java
  • 门控时钟和时钟使能

    门控时钟

    时钟使能电路是同步设计的重要基本电路,在很多设计中,虽然内部不同模块的处理速度不同,但是由于这些时钟是同源的,可以将它们转化为单一的时钟电路处理。在FPGA的设计中,分频时钟和源时钟的skew不容易控制,难以保证分频时钟和源时钟同相。故此推荐采用使用时钟使能的方法,通过使用时钟使能可以避免时钟“满天飞”的情况,进而避免了不必要的亚稳态发生,在降低设计复杂度的同时也提高了设计的可靠性。

    门控时钟 Verilog示例代码:

    input wr_n; //写使能信号,低有效

    input cs_n; //片选信号,低有效

    input[7:0] db; //输入数据总线

     

    output db_r; //锁存输出

     

    reg db_r; //输入数据寄存器

    wire d_clk; //门控时钟信号

     

    assign d_clk = wr_n || cs_n;

     

    always @ (posedge d_clk) //门控时钟上升沿

    db_r <= db; //锁存输入数据

     

    RTL Viewer:

     

     

    组合逻辑中多用门控时钟,一般驱动门控时钟的逻辑都是只包含一个与门(或门)。如果有其它的附加逻辑,容易因竞争产生不希望的毛刺。

     

    使能时钟

     

    Verilog示例代码:

    input clk; //50MHz时钟信号

    input wr_n; //写使能信号,低有效

    input cs_n; //片选信号,低有效

    input[7:0] db; //数据总线

     

    output db_r;

    reg db_r; //输入数据寄存器

    wire en; //使能信号

     

    assign en = ~wr_n && ~cs_n;

     

    always @ (posedge clk) //全局时钟上升沿

    if(en) //使能锁存输入

    db_r <= db; //锁存输入数据

     

    RTL Viewer:

     

     

    使能时钟这要是用于时序逻辑中,比门控时钟要来的稳定。

    上面只是一个举例,实际上它们实现的功能上还是有一点差别的。门控时钟一例中是能够比较准确的在wr_n的上升沿锁存数据的。而使能时钟一例中在wr_n有效期间的每个时钟周期都会锁存输入数据,最后写入结束后锁存寄存器里的数据是wr_n上升前的0-T(T=1/clk)时间内锁存的数据。因为是个例子,也就不详细说,具体情况具体分析。

     

    在某系统中,前级数据输入位宽为8,而后级的数据输出位宽32,我们需要将8bit的数据转换成32bit的数据,因此后级处理的时钟频率为前级的1/4,若不使用时钟时能,则就要将前级时钟进行4分频来作为后级处理的时钟,这种设计方法会引入新的时钟域,为了避免这种情况,我们采用了时钟时能的方法来减少设计的复杂度。

     

    module gray
    (
    input clk,
    input rst_n,
    input [7:0] data_in,
    outputreg [31:0] data_out,
    outputreg clk1x_en
    );

    reg [1:0] cnt;
    reg [31:0] shift_reg;

    always @ (posedge clk,negedge rst_n)
    begin
    if(!rst_n)
    cnt
    <=2'b0;
    else
    cnt
    <= cnt +1'b1;
    end

    always @ (posedge clk,negedge rst_n)
    begin
    if(!rst_n)
    clk1x_en
    <=1'b0;
    elseif(cnt ==2'b01)
    clk1x_en <=1'b1;
    else
    clk1x_en
    <=1'b0;
    end

    always @ (posedge clk,negedge rst_n)
    begin
    if(!rst_n)
    shift_reg
    <=32'b0;
    else
    shift_reg
    <= {shift_reg[23:0],data_in};
    end

    always @ (posedge clk,negedge rst_n)
    begin
    if(!rst_n)
    data_out
    <=32'b0;
    elseif(clk1x_en==1'b1)//仅在clk1x_en为1时才将shift_reg的值赋给data_out
    data_out<=shift_reg;
    end

    endmodule
  • 相关阅读:
    第三节 java 数组(循环遍历、获取数组的最值(最大值和最小值)、选择排序、冒泡排序、练习控制台输出大写的A)
    第三节 java 数组
    brpc
    thrift 总结
    C++ 中 # 和## 的使用
    查看系统句柄数
    zenuml
    shell脚本
    resize() reserve()函数的区别(vector)
    grep 用法
  • 原文地址:https://www.cnblogs.com/lueguo/p/3347152.html
Copyright © 2011-2022 走看看