1、如下 简单的不能再简单的程序
module top( clk,clk_out);
input clk;
output reg clk_out;
reg [2:0] cnt;
always@(posedge clk)
if(cnt==3'd4)
begin
cnt<=3'd0;
clk_out<=~clk_out;
end
else cnt<=3'd1+cnt;
endmodule
RTL视图
RTL 看看就行了,功能视图,不代表综合后的,差距还是很大很大滴 !
Technology Map Viewer
先不看clk_out,只关注 cnt 计数器。计数器和加法器的电路结构还是很不一样的 !
cnt 输入 输出 真值表
输入 输出
cnt[2] cnt[1] cnt[0] cnt[2] cnt[1] cnt[0]
0 0 0 0 0 1
0 0 1 0 1 0
0 1 0 0 1 1
0 1 1 1 0 0
1 0 0 0 0 0
1 0 1 1 1 0
1 1 0 1 1 1
1 1 1 0 0 0
写成逻辑函数 cnt[2]=cnt[2]'cnt[1]cnt[0]+cnt[2]cnt[1]'cnt[0]+cnt[2]cnt[1]cnt[0]'
=(cnt[2]$cnt[1])cnt[0]+cnt[2]cnt[1]cnt[0]'
注意: $代表异或;化简的方法 公式法和卡诺图法
对应的 cnt[2] 综合后的电路如下,上边cnt~2 放大既可以看到里边电路结构
这个电路模块在一个 LUT 中实现,LUT 实现这个电路是用 查找表SRAM 的方式!
cnt[1] 和cnt[0] 同样的道理(略) ;
到这里,不得不感慨 综合器的强大,把行为级的verilog描述转换成了电路 !省去了
真值表---逻辑函数---化简---电路 这一复杂的过程 !
也看到了计数器和加法器(串行进位加法器)是完全不同的电路结构 !
2、说说“行波时钟”
上边的 clk_out 就是一个“行波时钟”,其他时序逻辑产生 一个时钟clk_out
clk_out这个触发器(寄存器)再作为时钟源,驱动其他电路模块触发器的时钟接入端。
这不是一个太好的方式,当然相比于组合逻辑产生的“门控时钟”,这个时钟还是很不 错的 。“行波时钟”有延时的弊端,延时不好控制,到源寄存器和目的寄存器延时都不同,容易出现时序问题,而且驱动能力不强,毕竟不是全局时钟网路 !
如果就是需要通过计数分频产生一个时钟,怎么办 ??
“时钟使能”方式,通过修改"行波时钟"的生成逻辑,在“行波时钟”的上升沿(或下降沿)产生宽度为一个“基时钟”周期的正脉冲,把这个脉冲信号作为后级触发器的时钟使能信 号,用“基时钟”代替“行波时钟”作为后级触发器的时钟输入信号,从而把原本由“行波时钟”驱动的后级逻辑转换为由“基时钟”驱动,并采用新生成的时钟使 能信号来产生与“行波时钟”边沿对应的时序控制。这样一来,原本由两个时钟驱动的复杂同步电路(“行波时钟”方案并不能看作异步时钟方案)就转化为了由同一个“基时钟”驱动的简单同步电路。(此段转自riple的博文)
例如:
module top( clk,dataout);
input clk;
output reg [3:0]dataout;
wire en;
reg [2:0] cnt;
always@(posedge clk)
if(cnt==3'd4)
begin
cnt<=3'd0;
end
else cnt<=3'd1+cnt;
assign en=(cnt==3'd4);
always@(posedge clk )
if(en)
begin dataout<=dataout+4'd1; end
endmodule