[文檔].艾米電子 – 分頻器,Verilog

來源:互聯網
上載者:User
文章目錄
  • 1 從計數器到分頻器
  • 2 偶數分頻器
  • 3 奇數分頻器
對讀者的假設

已經掌握:

  • 可程式化邏輯基礎
  • Verilog HDL基礎
  • 使用Verilog設計的Quartus II入門指南
  • 使用Verilog設計的ModelSIm入門指南
內容1 從計數器到分頻器

此處所說的分頻器,即把輸入時鐘的頻率降低後再輸出時鐘的模組。今天我們只討論等占空比的偶數分頻和奇數分頻,關於小數分頻以及倍頻將不做介紹,有興趣的朋友可以自行研究。在之之前我們先看下前面講的模-m計數器。

代碼1.1 模-m計數器(預設為模-10計數器)

module mod_m_bin_counter#(parameter M=10) // mod-M(  // global clock and asyn reset  input clk,  input rst_n,  // counter interface  output max_tick,  output min_tick,  output [N-1:0] q);// signal declarationlocalparam N = log2(M); // number of bits in counterreg [N-1:0] r_reg;wire [N-1:0] r_next;// body// registeralways@(posedge clk, negedge rst_n)  if(!rst_n)    r_reg <= 0;  else    r_reg <= r_next;   // next-state logicassign r_next = (r_reg == (M-1)) ? 0 : r_reg + 1'b1;//output logicassign q = r_reg;assign max_tick = (r_reg == (M-1)) ? 1'b1 : 1'b0;// log2 constant functionfunction integer log2(input integer n);  integer i;begin  log2 = 1;  for(i=0; 2**i<n; i = i + 1)    log2 = i + 1;endendfunction                endmodule

根據這個模-m計數器,我們再寫一個testbench。

代碼1.2 模m-計數器的testbench(重新設定為模-10計數器)

`timescale 1ns/1nsmodule f_div_tb;localparam T=20; // clock periodlocalparam M = 10;localparam N = log2(M);// global clock and asyn resetreg clk, rst_n;wire o_clk;// counter interfacewire max_tick, min_tick;wire [N-1:0] q;// log2 constant functionfunction integer log2(input integer n);  integer i;begin  log2 = 1;  for(i=0; 2**i<n; i = i + 1)    log2 = i + 1;endendfunction// clcokalwaysbegin  clk = 1'b0;   #(T/2);  clk = 1'b1;  #(T/2);end// resetinitialbegin  rst_n = 1'b0;  #(T/2)  rst_n = 1'b1;end// instmod_m_bin_counter #(.M(M)) m_inst(  .clk(clk),  .rst_n(rst_n),  .max_tick(max_tick),  .min_tick(min_tick),  .q(q));// stimulus bodyinitial begin  // initial input   @(posedge rst_n); // wait to deassert rst_n  @(negedge clk); // wait for a clock  // run 1024 cock cycle  repeat(1024) @(negedge clk); // last 1024 clock cycle  $stop;endendmodule

但是我在使用Quartus II + Modelsim_Altera模擬的時候出現了下面的錯誤提示。

代碼2的第10行,變數N未定義,然後第11行用N來索引的q數組也沒有定義。奇怪了,我在Quartus II都能綜合通過,而且RTL視圖也是正確的,為什麼Modelsim_Altera就不可以這樣定義呢?咳,把常量(localparam)換成參數(parameter)即可。

代碼1.3 改進後的模-m計數器(重新設定為模-10計數器)

module mod_m_bin_counter#(parameter M=10, N = log2(M)) // mod-M(  // global clock and asyn reset  input clk,  input rst_n,  // counter interface  output max_tick,  output min_tick,  output [N-1:0] q);// signal declaration//localparam N = log2(M); // number of bits in counterreg [N-1:0] r_reg;wire [N-1:0] r_next;// body// registeralways@(posedge clk, negedge rst_n)  if(!rst_n)    r_reg <= 0;  else    r_reg <= r_next;   // next-state logicassign r_next = (r_reg == (M-1)) ? 0 : r_reg + 1'b1;//output logicassign q = r_reg;assign min_tick = (r_reg == 0) ? 1'b1 : 1'b0;assign max_tick = (r_reg == (M-1)) ? 1'b1 : 1'b0;// log2 constant functionfunction integer log2(input integer n);  integer i;begin  log2 = 1;  for(i=0; 2**i<n; i = i + 1)    log2 = i + 1;endendfunction                endmodule

修改完,在Quartus II裡再綜合一下。接下來就是按照[文檔].艾米電子 - 使用Verilog設計的Quartus II入門指南再做一次模擬。告訴大家一個技巧,如果執行完一次RTL級或門級的模擬,那麼Quartus II會為我們的主模組及其testbench產生do檔案的。這樣假如有錯誤,就無需重新啟動Modelsim_Altera,只需重新load一下do檔案即可。

(路徑格式:Quarter II工程檔案夾\simulation\modelsim\mod_m_bin_counter_run_msim_rtl_verilog.do)

下面看下RTL級模擬波形。

 

下面討論一下如何測量波形的長度,我們注意兩個工具。在Modelsim>Windows處,開啟 ,對應的工具為 。下面在波形上加( )幾個Cursor,使用滑鼠調整其位置。

注意紅色地區及標識,我們可以清楚地看到兩個Cursor之間的距離為20, 000ps,亦即20ns,也就是模-10計數器的周期。那麼怎麼讓它顯示20ns呢?在座標軸地區( ),右鍵選擇 ,設定所需時間單元。

修改為ns,順便測一下max_tick和min_tick脈衝的期間,顯示如下:

 

測量完,可通過 ,把不需要的Cursor去掉。

換一種視角看波形。

假設我們以max_tick作為使能訊號,來翻轉某個寄存器,那麼這個變數就會輸出方波,且其周期為模-m周期的2倍。

這就是偶數分頻器的原理。

 

假如我們分別使用全域時鐘的上升沿和下降沿觸發計數器,然後根據兩個計數器的值來產生時鐘,再拿這兩個時鐘運算,得到所需分頻的時鐘。下面以模-3計數器為例來說明如何3分頻。

方法1

黃色地區分別為分別使用全域時鐘的上升沿和下降沿觸發計數器;綠色地區為根據兩個計數器的輸出q產生的兩個脈衝訊號;青色地區為所需分頻時鐘。

綠色地區是0 ~ 3>>1輸出低電平,3>> ~ 3-1輸出高電平;對應的綠色地區做按位或運算。

方法2

綠色地區是0 ~ 3>>1輸出高電平,3>> ~ 3-1輸出低電平;對應的綠色地區做按位與運算。

以上就是技術分頻的原理。

2 偶數分頻器

根據第1節的解析,下面我們寫一個偶數分頻的案例。

代碼 2.1 偶數分頻(預設分頻比為50, 000, 000)

module f_div#(parameter RATIO=50_000_000)(  // global clock and asyn reset  input clk,  input rst_n,  //output clock  output reg o_clk);wire max_tick;mod_m_bin_counter #(.M(RATIO/2)) mod_m_inst(  .clk(clk),  .rst_n(rst_n),  .max_tick(max_tick),  .min_tick(),  .q());always@(posedge clk, negedge rst_n)  if(!rst_n)    o_clk <= 1'b0;  else if(max_tick)    o_clk <= ~o_clk;endmodule

第22~26行,我們使用模-m計數器的max_tick來作為時鐘使能,驅動o_clk翻轉。注意第13行的模-m例化參數中,M的值為分頻比RATIO的一半。

下面給出testbench。

代碼2.2 偶數分頻的testbench(重新設定為6分頻)

`timescale 1ns/1nsmodule f_div_tb;localparam RATIO = 6;localparam T=20; // clock period// global clock and asyn resetreg clk, rst_n;wire o_clk;// clcokalwaysbegin  clk = 1'b0;   #(T/2);  clk = 1'b1;  #(T/2);end// resetinitialbegin  rst_n = 1'b0;  #(T/2)  rst_n = 1'b1;end// instf_div #(.RATIO(RATIO)) f_div_inst(  .clk(clk),  .rst_n(rst_n),  .o_clk(o_clk));// stimulus bodyinitial begin  // initial input   @(posedge rst_n); // wait to deassert rst_n  @(negedge clk); // wait for a clock  // run 1024 cock cycle  repeat(1024) @(negedge clk); // last 1024 clock cycle  $stop;endendmodule

RTL級模擬波形如下所示。觀察3個Cursor的間距,分別為120ns、20ns,即實現了6分頻動作。

 

3 奇數分頻器

講完了偶數分頻,下面再寫個奇數分頻。

代碼3.1 奇數分頻(預設為25分頻)

module f_div#(parameter RATIO=25)(  // global clock and asyn reset  input clk,  input rst_n,  //output clock  output o_clk_p, o_clk_n, o_clk);// log2 constant functionfunction integer log2(input integer n);  integer i;begin  log2 = 1;  for(i=0; 2**i<n; i = i + 1)    log2 = i + 1;endendfunctionlocalparam N = log2(RATIO);wire [N-1:0] q_pos, q_neg;mod_m_bin_counter #(.M(RATIO)) mod_m_inst1(  .clk(clk),  .rst_n(rst_n),  .max_tick(),  .min_tick(),  .q(q_pos));mod_m_bin_counter #(.M(RATIO)) mod_m_inst2(  .clk(~clk),  .rst_n(rst_n),  .max_tick(),  .min_tick(),  .q(q_neg)); assign o_clk_p = (q_pos <= RATIO>>1) ? 0 : 1; assign o_clk_n = (q_neg <= RATIO>>1) ? 0 : 1;assign o_clk = o_clk_n | o_clk_p;  endmodule

第24~31行和第33~40行,我們分別例化了兩個相同參數的模-m計數器,不同點在於第26行和第35行的區別,即上升沿觸發和下降沿觸發兩種。

下面給出testbench。

代碼3.2 奇數分頻的testbench(重新設定為5分頻)

`timescale 1ns/1nsmodule f_div_tb;localparam RATIO = 5;localparam T=20; // clock period// global clock and asyn resetreg clk, rst_n;wire o_clk_p, o_clk_n, o_clk;// clcokalwaysbegin  clk = 1'b0;   #(T/2);  clk = 1'b1;  #(T/2);end// resetinitialbegin  rst_n = 1'b0;  #(T/2)  rst_n = 1'b1;end// instf_div #(.RATIO(RATIO)) f_div_inst(  .clk(clk),  .rst_n(rst_n),  .o_clk_p(o_clk_p),  .o_clk_n(o_clk_n),  .o_clk(o_clk));// stimulus bodyinitial begin  // initial input   @(posedge rst_n); // wait to deassert rst_n  @(negedge clk); // wait for a clock  // run 1024 cock cycle  repeat(1024) @(negedge clk); // last 1024 clock cycle  $stop;endendmodule 

下面給出RTL層級模擬波形。紅圈內的Cursor測距顯示,5分頻OK。

 

好了,今天就囉嗦到這裡,大家有什麼疑問可以留言討論。

參考

[筆記].等占空比分頻器的幾種寫法.[Verilog]

另見

[與艾米一起學FPGA/SOPC].[邏輯實驗文檔連載計劃]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.