如何将信号delay n个Clk?

转载地址:http://www.cnblogs.com/oomusou/archive/2009/06/15/verilog_dly_n_clk.html

Abstract
在實務上為了與其他信號同步,常會故意delay幾個clk,本文整理出幾種常見的coding style。

Introduction
使用環境:NC-Verilog 5.4 + Debussy 5.4 + Quartus II 9.0

為什麼需要將值delay n的clk呢?比如說我想運算A+B,目前這個clk A已經到了,但B必須delay 3個clk之後才會到,為了運算A+B,勢必使用shift register將A delay 3個clk之後,才能與B同步,所以希望先做出delay 3個clk的功能,進而實作出delay n個clk。

Method 1:
delay_3t.v / Verilog
 

复制代码
1  /*  
2  (C) OOMusou 2009  http://oomusou.cnblogs.com
3 
4  Filename    : delay_3t.v
5  Compiler    : NC-Verilog 5.4
6  Description : delay 3t method 1
7  Release     : 06/15/2009 1.0
8  */
9 
10  module  delay_3t (
11    clk,
12    rst_n,
13    d,
14    q
15  );
16 
17  input   clk;
18  input   rst_n;
19  input   d;
20  output  q;
21 
22  reg  d_dly_1t;
23  reg  d_dly_2t;
24  reg  d_dly_3t;
25 
26  assign  q  =  d_dly_3t;
27 
28  always @( posedge  clk  or   negedge  rst_n)  begin
29     if  ( ! rst_n)  begin
30      d_dly_1t  <=   0 ;
31      d_dly_2t  <=   0 ;
32      d_dly_3t  <=   0 ;
33     end
34     else   begin
35      d_dly_1t  <=  d;
36      d_dly_2t  <=  d_dly_1t;
37      d_dly_3t  <=  d_dly_2t;
38     end
39  end
40 
41  endmodule
复制代码


Testbench
delay_3t_tb.v / Verilog

复制代码
1  /*  
2  (C) OOMusou 2009  http://oomusou.cnblogs.com
3 
4  Filename    : delay_3t_tb.v
5  Compiler    : NC-Verilog 5.4
6  Description : delay 3t method 1
7  Release     : 06/15/2009 1.0
8  */
9 
10  ` include   " delay_3t.v "
11 
12  module  delay_3t_tb;
13 
14  reg  clk;
15  reg  rst_n;
16  reg  d;
17  wire  q;
18 
19  delay_3t u0 (
20    .clk(clk),
21    .rst_n(rst_n),
22    .d(d),
23    .q(q)
24  );
25 
26  initial   begin
27    $fsdbDumpfile( " delay_3t.fsdb " );
28    $fsdbDumpvars( 0 , delay_3t_tb);
29  end
30 
31  //  clk
32  initial   begin
33    clk  =   0 ;
34     forever  # 10  clk  =   ~ clk;
35  end
36 
37  initial   begin
38    rst_n  =   0 ;
39    d  =   0 ;
40    # 20 ;
41    rst_n  =   1 ;
42    # 11 ;
43    d  =   1 ;
44    # 20 ;
45    d  =   0 ;
46    # 500 ;
47    $finish;
48  end
49 
50  endmodule
复制代码


模擬結果

del00

這是最常見,也最直覺的寫法。一個D-FF會delay 1個clk,要delay 3個clk,所以就用3個D-FF,經過模擬,q也的確delay了3個clk。

Method 2:
delay_3t.v / Verilog

复制代码
1  /*  
2  (C) OOMusou 2009  http://oomusou.cnblogs.com
3 
4  Filename    : delay_3t.v
5  Compiler    : NC-Verilog 5.4
6  Description : delay 3t method 2
7  Release     : 06/15/2009 1.0
8  */
9 
10  module  delay_3t (
11    clk,
12    rst_n,
13    d,
14    q
15  );
16 
17  input   clk;
18  input   rst_n;
19  input   d;
20  output  q;
21 
22  reg  d_dly_1t;
23  reg  d_dly_2t;
24  reg  d_dly_3t;
25 
26  assign  q  =  d_dly_3t;
27 
28  always @( posedge  clk  or   negedge  rst_n)  begin
29     if  ( ! rst_n)
30      {d_dly_3t, d_dly_2t, d_dly_1t}   <=   0 ;
31     else
32      {d_dly_3t, d_dly_2t, d_dly_1t}  <=  {d_dly_2t, d_dly_1t, d};
33  end
34 
35  endmodule
复制代码


Testbench與模擬的波型圖與Method 1完全一樣,所以加以省略。這種寫法在DE2的範例也曾經出現過,思維仍是3個D-FF,只是寫法比較tricky,利用了Verilog特有的{}語法,一行就解決,比Method 1更精簡。

不過這兩個寫法都有個問題,若要delay 10個clk,就得宣告10個reg,程式相當冗長,是否有更簡單的寫法呢?

我們知道Quartus II最後都會將我們寫的RTL code加以最佳化,來看看經過Quartus II編譯後,RTL Viewer長怎樣?

delay01

在合成之後,Quartus II僅用了一個3 bit的D-FF,將output q再接回d 2次,而達成delay 3個clk,並不是如我們原本所想的,使用了3個D-FF串聯。我們將這種硬體思維,再次用Verilog表達。

Method 3:
使用for

delay_nt.v / Verilog

复制代码
1  /*  
2  (C) OOMusou 2009  http://oomusou.cnblogs.com
3 
4  Filename    : delay_nt.v
5  Compiler    : NC-Verilog 5.4
6  Description : delay 3t method 3
7  Release     : 06/15/2009 1.0
8  */
9 
10  module  delay_nt (
11    clk,
12    rst_n,
13    d,
14    q
15  );
16 
17  parameter  n  =   1 ;
18 
19  input   clk;
20  input   rst_n;
21  input   d;
22  output  q;
23 
24  reg  [n - 1 : 0 ] r;
25 
26  assign  q  =  r[n - 1 ];
27 
28  integer  i;
29 
30  always @( posedge  clk  or   negedge  rst_n)  begin
31     if  ( ! rst_n) 
32      r  <=   0 ;
33     else   begin
34       for (i = 0 ; i < n - 1 ; i = i + 1 )
35        r[i + 1 <=  r[i];
36        
37      r[ 0 <=  d;
38     end
39  end
40 
41  endmodule
复制代码


既然要做個通用的shift register,很直覺的會想到用for,這種寫法在很多書上都曾看過,就我印象中,在J. BHASKERVerilog HDL Primer吳戈Verilog HDL與數字系統設計簡明教程這兩本書都用這種寫法。不過使用for仍不是最精簡的寫法。

Method 4:
delay_nt.v / Verilog

复制代码
1  /*  
2  (C) OOMusou 2009  http://oomusou.cnblogs.com
3 
4  Filename    : delay_nt.v
5  Compiler    : NC-Verilog 5.4
6  Description : delay 3t method 4
7  Release     : 06/15/2009 1.0
8  */
9 
10  module  delay_nt (
11    clk,
12    rst_n,
13    d,
14    q
15  );
16 
17  parameter  n  =   3 ;
18 
19  input   clk;
20  input   rst_n;
21  input   d;
22  output  q;
23 
24  reg  [n - 1 : 0 ] r;
25 
26  assign  q  =  r[n - 1 ];
27 
28  always @( posedge  clk  or   negedge  rst_n)  begin
29     if  ( ! rst_n) 
30      r  <=   0 ;
31     else
32      r  <=  {r, d};  
33  end
34 
35  endmodule
复制代码


{}寫法是Verilog的獨門絕技,這樣就不再需要for,這也是為什麼Verilog寧願從C語言搶走{}換來begin, end,因為{}這種合併的寫法非常的好用。Testbench與模擬波型圖也與Method 1與Method 2一樣,再次省略。這種寫法使用了parameter,無論要delay幾個clk,只需修改n即可,而且與Quartus II最佳化後的硬體一樣,我們再次將編譯過的RTL Viewer打開做驗證。

delay02

完整程式碼下載
delay_3t.7z (Method 1)
delay_3t2.7z (Method 2)
delay_nt2.7z (Method 3)
delay_nt.7z (Method 4)

Conclusion
這4種寫法最後合出來的硬體都一樣,表示現在的合成器都夠聰明,差別只是在哪種coding style較好,將來比較好維護。另外也是開開眼界,若將來閱讀其他人的code,馬上就知道對方想表達的意思。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值