门控时钟和时钟使能

FPGA设计中,我们经常会使用分频的方法来得到一个我们需要的时钟频率,而在很多开发板厂家配套的教程里,他们常常会使用计数器分频得到的高低电平时钟来当做驱动时钟,这种方法简单易懂,但是,在工程设计中,这种方法是不被允许的。

门控时钟

门控时钟就是使用计数器和逻辑门翻转来产生的时钟,下面是典型的门控时钟

//生成I2C的SCL的四倍频率的驱动时钟用于驱动i2c的操作
always @(posedge sys_clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        dri_clk <=  1'b1;
        clk_cnt <= 10'd0;
    end
    else if(clk_cnt == clk_divide - 1'd1) begin
        clk_cnt <= 10'd0;
        dri_clk <= ~dri_clk;
    end
    else
        clk_cnt <= clk_cnt + 1'b1;
end

//(三段式状态机)同步时序描述状态转移
always @(posedge dri_clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        cur_state <= st_idle;
    else
        cur_state <= next_state;
end

在上面代码中,先使用sys_clk生成一个dri_clk,然后再使用dri_clk来驱动其他的电路,这种方法是绝对不允许的,主要有以下两点原因:

1、dri_clk是由逻辑门生成的,会有可能产生毛刺

2、dri_clk经过了逻辑门,从sys_clk触发到dri_clk稳定输出会有一定的延迟,这样dri_clk和sys_clk以及其他的门控时钟会有一定的相位差,这在大型系统或者比较严格的系统中是很危险的。

时钟使能

时钟使能的方法就能有效的解决以上两个缺点
时钟使能也会用到计数器,但是不会用到反相器,生成的信号也不会直接用于其他电路的触发,就以上面的代码为例子进行修改,时钟使能的代码如下:

//生成I2C的SCL的四倍频率的驱动时钟用于驱动i2c的操作
always @(posedge sys_clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        dri_clk <=  1'b0;
        clk_cnt <= 10'd0;
    end
    else if(clk_cnt == clk_divide - 1'd1) begin
        clk_cnt <= 10'd0;
        dri_clk <= 1'b1;
    end
    else begin
        clk_cnt <= clk_cnt + 1'b1;
        dri_clk <= 1'b0;
    end
end

//(三段式状态机)同步时序描述状态转移
always @(posedge sys_clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        cur_state <= st_idle;
    else
    	begin
    		if(dri_clk == 1'b1)
        		cur_state <= next_state;
        	else
        		;
        end
end

可以看到,在上面代码中,也使用到了计数器,但是仅仅是用于产生一个时钟使能脉冲信号,只持续一个sys_clk。
而dri_clk也没有直接用于驱动其他电路,在整个系统中,所有的时钟都是sys_clk,这样就不会有相位不匹配的问题存在了,而且也不会出现由于毛刺带来的影响。

上一篇:UI自动化之 python2.7 升级到python3.6 module 'sys' has no attrbute 'setdefaultencoiding'


下一篇:Nginx防盗链、Nginx访问控制、Nginx解析php相关配置、Nginx代理