
在FPGA设计中,我们经常会使用分频的方法来得到一个我们需要的时钟频率,而在很多开发板厂家配套的教程里,他们常常会使用计数器分频得到的高低电平时钟来当做驱动时钟,这种方法简单易懂,但是,在工程设计中,这种方法是不被允许的。
门控时钟就是使用计数器和逻辑门翻转来产生的时钟,下面是典型的门控时钟
//生成I2C的SCL的四倍频率的驱动时钟用于驱动i2c的操作
always @(posedge sys_clk or negedge rst_n) beginif(rst_n == 1'b0) begindri_clk <= 1'b1;clk_cnt <= 10'd0;endelse if(clk_cnt == clk_divide - 1'd1) beginclk_cnt <= 10'd0;dri_clk <= ~dri_clk;endelseclk_cnt <= clk_cnt + 1'b1;
end//(三段式状态机)同步时序描述状态转移
always @(posedge dri_clk or negedge rst_n) beginif(rst_n == 1'b0)cur_state <= st_idle;elsecur_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) beginif(rst_n == 1'b0) begindri_clk <= 1'b0;clk_cnt <= 10'd0;endelse if(clk_cnt == clk_divide - 1'd1) beginclk_cnt <= 10'd0;dri_clk <= 1'b1;endelse beginclk_cnt <= clk_cnt + 1'b1;dri_clk <= 1'b0;end
end//(三段式状态机)同步时序描述状态转移
always @(posedge sys_clk or negedge rst_n) beginif(rst_n == 1'b0)cur_state <= st_idle;elsebeginif(dri_clk == 1'b1)cur_state <= next_state;else;end
end
可以看到,在上面代码中,也使用到了计数器,但是仅仅是用于产生一个时钟使能脉冲信号,只持续一个sys_clk。
而dri_clk也没有直接用于驱动其他电路,在整个系统中,所有的时钟都是sys_clk,这样就不会有相位不匹配的问题存在了,而且也不会出现由于毛刺带来的影响。
本文发布于:2024-03-05 17:21:59,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/1709700442124071.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
| 留言与评论(共有 0 条评论) |