lijieamd 发表于 2012-6-25 15:12:32

一个关于时序逻辑的困惑,希望大家一起讨论

本帖最后由 lijieamd 于 2012-6-25 15:13 编辑

我在用verilog描述时序电路时,始终有一个问题困扰我,可能确实有这个问题存在,也可能是我的理解不到位,现在我将问题描述出来,希望大家能一起讨论。

always@(negedge rst or posedge clk)
        begin
                if(~rst)
                begin
                        counter = 8'd0;
                end
                else
                begin
                        counter = counter + 8'd1;
                end       
        end

        always@(negedge rst or posedge clk)
        begin
                if(~rst)
                begin
                        A = 1'b0;
                end
                else if(counter == 8'd2)
                begin
                        A = 1'b1;
                end
        end

很简单的一个代码,clk上升沿驱动counter计数,在clk上升沿判断counter值,如果等于2,输出A=1

生成的RTL图和仿真波形如下




我对RTL图的理解是这样,在第一个clk上升沿到来之前,counter的触发器输出是8’d0,输入是8’d1,第一个clk上升沿到来后,输出8’d1,第二个clk上升沿到来后,输出8’d2。
此时Equal0将输出1,A的触发器被使能,而同时第二个clk上升沿会使A的Q=D。

问题就在这里,也就是A触发器的ENA和触发端信号的先后问题。
从仿真图来看,触发端的clk上升沿应该来的更快,因为第二个clk上升沿的时候,A输出任然为0,到第三个clk上升沿,A才输出1。实际上我是想让第二个clk上升沿就输出A=1

如果出现下面这种情况



也就是在FPGA内部,clk到A触发器的走线长度远远大于到counter触发器的走线。那么在A和counter的触发端会有一个可观的延时,也就是时钟偏斜(SKEW),那么这样的话,在第二个clk上升沿到达A触发器的时候, A触发器的ENA端已经是1了,也就是说,在第二个clk上升沿,A就已经输出1了,这和仿真就不同了。

这是否意味着,这个verilog描述本就存在问题?
如果我想在任何情况下,都会稳定的在第二个clk上升沿使A输出1,应该如何实现呢?

希望大家能给我一些帮助,谢谢。

lanliang714 发表于 2012-6-25 15:32:04

本帖最后由 lanliang714 于 2012-6-25 15:48 编辑

verilog描述问题,
可改为:assign A = (counter >= 8'd2) ? 1'b1 : 1'b0;

或者
always@(negedge rst or posedge clk)
      begin
                if(~rst)
                begin
                        A = 1'b0;
                end
                else if(counter == 8'd1)
                begin
                        A = 1'b1;
                end
      end

pocker5200 发表于 2012-6-25 16:36:43

时钟线走全局时钟网络,它可以保证时钟信号到达各个目标逻辑单元的时延基本相同。
有条件的话,把代码下载到板子上跑一下,用逻辑分析仪看结果。

lijieamd 发表于 2012-6-25 19:25:09

lanliang714 发表于 2012-6-25 15:32 static/image/common/back.gif
verilog描述问题,
可改为:assign A = (counter >= 8'd2) ? 1'b1 : 1'b0;



写成 (counter == 8'd1) 的确能使得在第二个clk上升沿输出A=1,但是如果发生时钟偏斜,是不是可能像我上面所说的那样,就在第一个clk上升沿就已经输出A了呢

因为我想在多个counter值进行不同的逻辑操作,如果用组合逻辑的话,还行吗?

lijieamd 发表于 2012-6-25 19:28:00

pocker5200 发表于 2012-6-25 16:36 static/image/common/back.gif
时钟线走全局时钟网络,它可以保证时钟信号到达各个目标逻辑单元的时延基本相同。
有条件的话,把代码下载 ...

那有没有一种时序逻辑描述方法,即使发生了一定程度的时钟偏斜,任然会正常工作呢?

wye11083 发表于 2012-6-25 23:16:37

只要你的设计能满足时序约束,下到板子上就跟仿真一样。唯一要注意的是仿真时使用的一些信号要做一些调整,否则仿真结果不正确。

岭上开花 发表于 2012-6-26 00:09:21

如果这样写呢?

always@(negedge rst or posedge clk)
      begin
                if(~rst)
                begin
                        counter = 8'd0;
                        A=1'b0;
                end
                else
                begin
                        counter = counter + 8'd1;
                        if (counter==8'b2) A=1'b1;
                end      
      end

lanliang714 发表于 2012-6-26 09:11:09

lijieamd 发表于 2012-6-25 19:25 static/image/common/back.gif
写成 (counter == 8'd1) 的确能使得在第二个clk上升沿输出A=1,但是如果发生时钟偏斜,是不是可能像我上 ...

多个counter值进行不同的逻辑操作??
不明白是啥意思?说具体点

lijieamd 发表于 2012-6-26 13:27:41

岭上开花 发表于 2012-6-26 00:09 static/image/common/back.gif
如果这样写呢?

always@(negedge rst or posedge clk)


谢谢,这样写是没问题,但是如果有多种输出,需要每种输出一个always的话,好像就没办法这样了

lijieamd 发表于 2012-6-26 13:28:41

lanliang714 发表于 2012-6-26 09:11 static/image/common/back.gif
多个counter值进行不同的逻辑操作??
不明白是啥意思?说具体点

也就是说有很多输出或者其他逻辑依赖于这个counter,如果每种一个always的话,不知道应该如何描述

at90s 发表于 2012-6-26 14:20:03

lijieamd 发表于 2012-6-25 19:25 static/image/common/back.gif
写成 (counter == 8'd1) 的确能使得在第二个clk上升沿输出A=1,但是如果发生时钟偏斜,是不是可能像我上 ...

如果时钟偏斜达到足以引起逻辑错误,布局布线工具会给出报告的。

岭上开花 发表于 2012-6-26 15:22:32

lijieamd 发表于 2012-6-26 13:27 static/image/common/back.gif
谢谢,这样写是没问题,但是如果有多种输出,需要每种输出一个always的话,好像就没办法这样了
...

多输出的话这样写:
always@(negedge rst or posedge clk)
      begin
                if(~rst)
                begin
                        counter = 8'd0;
                end
                else
                begin
                        counter = counter + 8'd1;
                end      
      end

always@(counter)
begin
      if (counter==8'd0)
      begin
                A<=1'b0;
                ......
      end
      else if (counter==8'd2)
      begin
                A<=1'b1;
                ......
      end
end

pocker5200 发表于 2012-6-26 19:36:30

这些问题尽可能交给综合器去解决吧……

aammoo 发表于 2012-6-26 19:53:19

这个跟时钟的延时没关系,时钟上升沿到来时计数器从一变到二,而这一时刻触发器A的输入仍然为0。跟两个触发器串联起来是一个道理的。

aammoo 发表于 2012-6-26 19:57:55

想在第二个时钟的上升沿让A稳定的输出1,可以考虑让计数器在下降沿计数,判断的always块在上升沿判断,让他们的时钟错开,复位也要用同步的。

aammoo 发表于 2012-6-26 20:05:30

7楼的的写法用的阻塞赋值,同一个块中的语句是按顺序执行的,而不是并发的,所以没问题。一般推荐用<=非阻塞赋值的方式。

lijieamd 发表于 2012-6-26 20:39:33

aammoo 发表于 2012-6-26 20:05 static/image/common/back.gif
7楼的的写法用的阻塞赋值,同一个块中的语句是按顺序执行的,而不是并发的,所以没问题。一般推荐用 ...

谢谢回复,我也观察过用阻塞赋值生成的RTL图,确实前后调换会改变电路
页: [1]
查看完整版本: 一个关于时序逻辑的困惑,希望大家一起讨论