工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Verilog

Verilogクロックジェネレータ:設計と実装ガイド

クロックは、異なるブロックを互いに同期させることを可能にするため、デジタル回路の構築に不可欠です。

クロックの特性

デジタルクロックの主要な特性は、クロック周期を決定する周波数、デューティサイクル、および他のクロックとの関係でのクロック位相です。

クロック周期

周波数は、一定期間内に何サイクル存在するかを示します。したがって、クロック周期は1サイクルを完了するのにかかる時間です。

クロックデューティサイクル

クロックがハイレベルである時間の、周期に対する割合がデューティサイクルを定義します。

クロック位相

1サイクルのクロックを360度の完全な円と見なせる場合、別のクロックは円上の異なる位置に相対的に配置され、異なる位相を占めます。例えば、同じ周期の別のクロックが右に1/4周期シフトしている場合、位相差は90度と言えます。

Verilogクロックジェネレータ

シミュレーションは、timescaleディレクティブで指定される限られた精度を持つ所定のtimescaleで動作する必要があります。したがって、timescaleの精度がクロック周期を表現するのに十分かどうかが重要です。例えば、クロック周波数が640000 kHzに設定されている場合、クロック周期は1.5625 nsになりますが、timescale精度が1psでは余分な桁を表現できないため十分ではありません。シミュレーションは最後の桁を丸めて3桁のtimescale精度に収めようとします。これによりクロック周期が1.563 nsになり、実際には639795 kHzを表すことになります!

以下のVerilogクロックジェネレータモジュールには、上記で説明した3つの特性を調整する3つのパラメータがあります。モジュールには、クロックを必要に応じて無効/有効にする入力enableがあります。複数のクロックが共通のenable信号で制御される場合、それらを相対的に位相合わせしやすくなります。

`timescale 1ns/1ps
module clock_gen (
  input enable,
  output reg clk
);
  parameter FREQ = 100000; // kHz単位
  parameter PHASE = 0;     // 度単位
  parameter DUTY = 50;     // パーセント単位
  
  real clk_pd = 1.0/(FREQ * 1e3) * 1e9; // nsに変換
  real clk_on = DUTY/100.0 * clk_pd;
  real clk_off = (100.0 - DUTY)/100.0 * clk_pd;
  real quarter = clk_pd/4;
  real start_dly = quarter * PHASE/90;
  reg start_clk;
  
  initial begin
    $display("FREQ = %0d kHz", FREQ);
    $display("PHASE = %0d deg", PHASE);
    $display("DUTY = %0d %%", DUTY);
    $display("PERIOD = %0.3f ns", clk_pd);
    $display("CLK_ON = %0.3f ns", clk_on);
    $display("CLK_OFF = %0.3f ns", clk_off);
    $display("QUARTER = %0.3f ns", quarter);
    $display("START_DLY = %0.3f ns", start_dly);
  end
  
  // 変数をゼロで初期化
  initial begin
    clk <= 0;
    start_clk <= 0;
  end
  
  // クロックがイネーブルされたとき、位相効果を得るために
  // クロック駆動を1に遅延させる。start_dlyは設定された
  // 位相に対する正しい遅延に設定される。enableが0のとき、
  // 現在のクロック周期を完了するのに十分な時間を許可
  always @ (posedge enable or negedge enable) begin
    if (enable) begin
      #(start_dly) start_clk = 1;
    end else begin
      #(start_dly) start_clk = 0;
    end
  end
  
  // 歪んだクロックオン/オフ時間でデューティサイクルを実現し、
  // クロックがオンの間はこれを継続
  always @(posedge start_clk) begin
    if (start_clk) begin
      clk = 1;
      while (start_clk) begin
        #(clk_on) clk = 0;
        #(clk_off) clk = 1;
      end
      clk = 0;
    end
  end
endmodule

異なるクロック周波数でのテストベンチ

module tb;
  wire clk1, clk2, clk3, clk4;
  reg enable;
  reg [7:0] dly;
  
  clock_gen u0(enable, clk1);
  clock_gen #(.FREQ(200000)) u1(enable, clk2);
  clock_gen #(.FREQ(400000)) u2(enable, clk3);
  clock_gen #(.FREQ(800000)) u3(enable, clk4);
  
  initial begin
    enable <= 0;
    for (int i = 0; i < 10; i= i+1) begin
      dly = $random;
      #(dly) enable <= ~enable;
      $display("i=%0d dly=%0d", i, dly);
      #50;
    end
    #50 $finish;
  end
endmodule
xcelium> run
FREQ = 100000 kHz
PHASE = 0 deg
DUTY = 50 %
PERIOD = 10.000 ns
CLK_ON = 5.000 ns
CLK_OFF = 5.000 ns
QUARTER = 2.500 ns
START_DLY = 0.000 ns
FREQ = 200000 kHz
PHASE = 0 deg
DUTY = 50 %
PERIOD = 5.000 ns
CLK_ON = 2.500 ns
CLK_OFF = 2.500 ns
QUARTER = 1.250 ns
START_DLY = 0.000 ns
FREQ = 400000 kHz
PHASE = 0 deg
DUTY = 50 %
PERIOD = 2.500 ns
CLK_ON = 1.250 ns
CLK_OFF = 1.250 ns
QUARTER = 0.625 ns
START_DLY = 0.000 ns
FREQ = 800000 kHz
PHASE = 0 deg
DUTY = 50 %
PERIOD = 1.250 ns
CLK_ON = 0.625 ns
CLK_OFF = 0.625 ns
QUARTER = 0.312 ns
START_DLY = 0.000 ns
i=0 dly=36
i=1 dly=129
i=2 dly=9
i=3 dly=99
i=4 dly=13
i=5 dly=141
i=6 dly=101
i=7 dly=18
i=8 dly=1
i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

異なるクロック位相でのテストベンチ

module tb;
  wire clk1, clk2;
  reg enable;
  reg [7:0] dly;
  
  clock_gen u0(enable, clk1);
  clock_gen #(.FREQ(50000), .PHASE(90)) u1(enable, clk2);
  
  initial begin
    enable <= 0;
    for (int i = 0; i < 10; i=i+1) begin
      dly = $random;
      #(dly) enable <= ~enable;
      $display("i=%0d dly=%0d", i, dly);
    end
    #50 $finish;
  end
endmodule
xcelium> run
FREQ = 100000 kHz
PHASE = 0 deg
DUTY = 50 %
PERIOD = 10.000 ns
CLK_ON = 5.000 ns
CLK_OFF = 5.000 ns
QUARTER = 2.500 ns
START_DLY = 0.000 ns
FREQ = 100000 kHz
PHASE = 90 deg
DUTY = 50 %
PERIOD = 10.000 ns
CLK_ON = 5.000 ns
CLK_OFF = 5.000 ns
QUARTER = 2.500 ns
START_DLY = 2.500 ns
FREQ = 100000 kHz
PHASE = 180 deg
DUTY = 50 %
PERIOD = 10.000 ns
CLK_ON = 5.000 ns
CLK_OFF = 5.000 ns
QUARTER = 2.500 ns
START_DLY = 5.000 ns
FREQ = 100000 kHz
PHASE = 270 deg
DUTY = 50 %
PERIOD = 10.000 ns
CLK_ON = 5.000 ns
CLK_OFF = 5.000 ns
QUARTER = 2.500 ns
START_DLY = 7.500 ns
i=0 dly=36
i=1 dly=129
i=2 dly=9
i=3 dly=99
i=4 dly=13
i=5 dly=141
i=6 dly=101
i=7 dly=18
i=8 dly=1
i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

異なるデューティサイクルでのテストベンチ

module tb;
  wire clk1, clk2, clk3, clk4;
  reg enable;
  reg [7:0] dly;
  
  clock_gen u0(enable, clk1);
  clock_gen #(.DUTY(25)) u1(enable, clk2);
  clock_gen #(.DUTY(75)) u2(enable, clk3);
  clock_gen #(.DUTY(90)) u3(enable, clk4);
  
  initial begin
    enable <= 0;
    for (int i = 0; i < 10; i= i+1) begin
      dly = $random;
      #(dly) enable <= ~enable;
      $display("i=%0d dly=%0d", i, dly);
      #50;
    end
    #50 $finish;
  end
endmodule
xcelium> run
FREQ = 100000 kHz
PHASE = 0 deg
DUTY = 50 %
PERIOD = 10.000 ns
CLK_ON = 5.000 ns
CLK_OFF = 5.000 ns
QUARTER = 2.500 ns
START_DLY = 0.000 ns
FREQ = 100000 kHz
PHASE = 0 deg
DUTY = 25 %
PERIOD = 10.000 ns
CLK_ON = 2.500 ns
CLK_OFF = 7.500 ns
QUARTER = 2.500 ns
START_DLY = 0.000 ns
FREQ = 100000 kHz
PHASE = 0 deg
DUTY = 75 %
PERIOD = 10.000 ns
CLK_ON = 7.500 ns
CLK_OFF = 2.500 ns
QUARTER = 2.500 ns
START_DLY = 0.000 ns
FREQ = 100000 kHz
PHASE = 0 deg
DUTY = 90 %
PERIOD = 10.000 ns
CLK_ON = 9.000 ns
CLK_OFF = 1.000 ns
QUARTER = 2.500 ns
START_DLY = 0.000 ns
i=0 dly=36
i=1 dly=129
i=2 dly=9
i=3 dly=99
i=4 dly=13
i=5 dly=141
i=6 dly=101
i=7 dly=18
i=8 dly=1
i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

enableのトグルでクロックの開始/停止

以下の波形は、enableがローのときクロックが停止し、enableがハイに設定されるとクロックが開始されることを示しています。

Verilog

  1. Verilogマスター:デジタル回路設計のための完全チュートリアル
  2. Verilog連結マスター:実践ガイド
  3. Verilog代入文の理解:種類、構文、ベストプラクティス
  4. Verilogブロッキング代入とノンブロッキング代入:違いを徹底解説
  5. Verilog関数のマスター:効率的なRTL設計のために
  6. Verilogタスクの理解:関数との違い、構文、使用法
  7. Verilog数学関数のマスター:効率的なハードウェア設計のために
  8. Verilog $timeformatのマスター:精度と表示制御
  9. 任意のスコープでのVerilog timescale理解と表示
  10. VerilogファイルI/Oの完全ガイド:オープン、読み取り、書き込み、クローズ
  11. Verilog入門:Hello World例で基本をマスター