(原創) 如何設計除頻器? (SOC) (Verilog) (MegaCore)

Abstract
循序電路第一個應用是拿來做計數器((筆記) 如何設計計數器? (SOC) (Verilog) (MegaCore)),有了計數器的基礎後,就可以拿計數器來設計除頻器,最後希望能做出能除N的萬用除頻器。

Introduction
使用環境:Quartus II 7.2 SP3 + ModelSim-Altera 6.1g

除頻器在實務中隨時會用到,如DE2只提供50MHz與27MHz的clock,如CMOS用的是25MHz,因此就必須手動作一個除頻器產生25MHz,利用計數器的基礎,就可以設計一個除頻器。

Method 1:
使用Verilog

除2的除頻器
最簡單的除頻器,還不需要到計數器就可以完成。

div2.v / Verilog (沒用到計數器)

1  /*  
2  (C) OOMusou 2008 http://oomusou.cnblogs.com
3 
4  Filename    : div2.v
5  Compiler    : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g
6  Description : Demo how to write frequency divider by 2
7  Release     : 07/12/2008 1.0
8  */
9 
10  module div2 (
11    input      clk,
12    input      rst_n,
13    output reg o_clk
14  );
15 
16  always@(posedge clk or negedge rst_n) begin
17    if ( ! rst_n)
18      o_clk <= 0 ;
19    else
20      o_clk <=   ~ o_clk;
21  end
22 
23  endmodule


頻率要變一半,也就是周期要變兩倍,也就是本來一個clock的時間,變成半個clock的時間,所以每次clock正源觸發時,剛好是0變1、1變0的時機。由於除2的除頻器很簡單,所以不需要用到記數器就可完成,但更複雜的除頻器一定要用到計數器,所以我們也用計數器寫一個除2除頻器,幫助了解後,才能寫更複雜的除頻器。

div2_v2.v / Verilog (使用計數器)

1  /*  
2  (C) OOMusou 2008 http://oomusou.cnblogs.com
3 
4  Filename    : div2_v2.v
5  Compiler    : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g
6  Description : Demo how to write frequency divider by 2
7  Release     : 07/12/2008 1.0
8  */
9 
10  module div2_v2 (
11    input      clk,
12    input      rst_n,
13    output reg o_clk
14  );
15 
16  reg cnt;
17 
18  always@(posedge clk or negedge rst_n) begin
19    if ( ! rst_n)
20      cnt <=   0 ;
21    else   if (cnt ==   1 ) // 0 ~ 1
22      cnt <=   0 ;
23    else
24      cnt <= cnt +   1 ;
25  end
26   
27  always@(posedge clk or negedge rst_n) begin
28    if ( ! rst_n)
29      o_clk <=   0 ;
30    else   if (cnt <   1 ) // 0
31      o_clk =   0 ;
32    else               // 1
33      o_clk =   1 ;
34  end
35 
36  endmodule


18行

always@(posedge clk or negedge rst_n) begin
 
if ( ! rst_n)
    cnt
<=   0 ;
 
else   if (cnt ==   1 ) // 0 ~ 1
    cnt <=   0 ;
 
else
    cnt
<= cnt +   1 ;
end


一個簡單的計數器,從0數到1,然後又重頭從0數到1,因為目前要做的是除2的除頻器,所以只需0和1兩個狀態即可。

27行

always@(posedge clk or negedge rst_n) begin
 
if ( ! rst_n)
    o_clk
<=   0 ;
 
else   if (cnt <   1 ) // 0
    o_clk =   0 ;
 
else               // 1
    o_clk =   1 ;
end


利用計數器產生新的clock,當計數器是0時,輸出1,當計數器是1時,輸出0。如此就完成duty cycle為50%的除2除頻器電路。

當然我可以將兩個always寫在一起,不過好的Verilog coding style建議每個always都短短的,最好一個always只處理一個register,第一個always block處理reg cnt,第二個處理reg o_clk,這樣一目了然,對於合成器來說,也較容易合成出好的電路,對於可讀性來說,人類也較容易理解,甚至看完code後,自己都可以當合成器,合出一個電路,這也是為什麼說寫HDL要『心中有電路』,而不是像寫軟體一樣,只要考慮語法就好,反正編譯器會幫你解決,這也是寫硬體和寫軟體另一個差異很大的地方。

testbench
div2_tb.v / Verilog

1  /*  
2  (C) OOMusou 2008 http://oomusou.cnblogs.com
3 
4  Filename    : div2_tb.v
5  Compiler    : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g
6  Description : Demo how to write frequency divider by 2 testbench
7  Release     : 07/16/2008 1.0
8  */
9  `timescale 1ns / 10ps
10  module div2_tb;
11  reg clk;
12  reg rst_n;
13  wire o_clk;
14 
15  div2 u0 (
16    .clk(clk),
17    .rst_n(rst_n),
18    .o_clk(o_clk)
19  );
20 
21  initial begin
22    clk   =   1 ' b1;
23    rst_n =   1 ' b1;
24
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值