当前位置:文档之家› 网上下载的一个三分频电路说明

网上下载的一个三分频电路说明

always@( negedge resetn or posedge clk or negedge clk) begin
if (resetn==1'b0)
begin
counter[2:0]<=3'd0;
out_clk<=1'b0;
end
else
begin
if (counter[2:0]==3'd5)
begin
counter[2:0]<=3'd0;
end
else
beign
counter[2:0]<= counter[2:0]+1;
end
////////////////////////////////////////////////////
if (counter[2:0]==3'd5 || counter[2:0]==3'd2)
begin
out_clk<=~out_clk;
end
end
end
其仿真结果是正确的
这个逻辑无法综合。

存在半导体工艺问题。

2.下面给出一个逻辑图。

逻辑是用器件画出来的,保证不存在物理上的实现问题。

仿真图如下:
也许有人要问,既然仿真都是对的,那么为什么要说实际中是80%工作呢?
看到波形图上的clk1(黄色)上的那些毛刺了么,毛刺并不可怕,但是这个电路工作的基础却是那些毛刺,准确地说,那些毛刺是必须有的,是工作过程的比不可少的部份。

这样的电路是否能正常工作就很让人匪夷所思了。

我们能不能让电路的正常功能不依赖于毛刺呢?
小结一下:
以上的思路都是试图在输入的clk上做改造,试图在恰当的地
方取正沿,恰当的地方取反沿。

但是要知道,这一定会导致竞争和冒险。

虽然逻辑上是可性的,但是实践中却没有那么简单。

这个时候,我们需要调整一下思路了:
能不能营造一个安全的时机来切换时钟沿的选择?显然,这需要在切换时钟沿时,强制时钟输出固定电平,当切换完成后,在取消这个强制条件。

对么?我们来试试看。

3. 看看以下的代码,也是一段有趣的东西。

always@(negedge resetn or posedge clk)
begin
if (resetn==1'b0)
begin
cnt1[1:0]<=2'd0;
end
else
begin
if(cnt1[1:0]==2'd2)
begin
cnt1[1:0]<=2'd0;
end
else
begin
cnt1[1:0]<=cnt1[1:0]+1;
end
end
end
always@(negedge resetn or negedge clk)
begin
if (resetn==1'b0)
begin
cnt2[1:0]<=2'd0;
end
else
begin
if(cnt2[1:0]==2'd2)
begin
cnt2[1:0]<=2'd0;
end
else
begin
cnt2[1:0]<=cnt2[1:0]+1;
end
end
end
always@*
begin
if (cnt1[1:0]==2'd2 || cnt2[1:0]==2'd0)
begin
clk1 = 1'b0;
end
else if (cnt1[1:0]==1'b1)
begin
clk1 = ~clk;
end
else
begin
clk1 = clk;
end
end
always@(negedge resetn or posedge clk1)
begin
if (resetn==1'b0)
begin
clk_out<=1'b0;
end
else
begin
clk_out<=~clk_out;
end
end
最后用的时钟clk1是clk和clk的反,但是在切换之间加上的强制为0的逻辑。

这段代码肯定是可综合的,而且简单的约束一下时序就可以生产。

但重要的是看了这段逻辑后我们突然明白了一件事情:要想长生质量好的3分频时钟,我们似乎必须要用到clk的下降沿来做点控制逻辑,这是被反复求证后逼出来的(不知道其它人是否有同感)。

那么我们为什么不愿意用下降沿触发的的寄存器呢?因为有些库里可能没有这样的器件,而必须在时钟树上上加反向。

如果有下降沿的寄存器,那么今后的扫瞄链又要多一些麻烦,虽然这些麻烦都可以客服,但是作为一个成熟的工程师要明白:尽量不要给自己找麻烦。

在工程上,最平常的东西最可靠。

4. 到这里我们的命题似乎解决了,但是我们的思考还不应该停止。

既然我们要用clk的下降沿,呢就完全可以打破以前的思路,来看看这个新的手段能给我们带来什么。

always@(negedge resetn or posedge clk)
begin
if (resetn==1'b0)
begin
cnt1[1:0]<=2'd0;
clk1<=1'b0;
end
else
begin
if(cnt1[1:0]==2'd2)
begin
cnt1[1:0]<=2'd0;
clk1<=1'b1;
end
else
begin
cnt1[1:0]<=cnt1[1:0]+1;
clk1<=1'b0;
end
end
end
always@(negedge resetn or negedge clk)
begin
if (resetn==1'b0)
begin
clk2<=2'd0;
end
else
begin
clk2<=clk1;
end
end
assign clk_out = clk1 | clk2;
代码似乎更简单了,思路也完全变了。

这回的思路是:先做一个简单的3分频电路,然后再调整占空比。

以这个思路,所有的1/N分频都可以解决。

相关主题