Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> Verilog

Verilog Clock Generator: Ontwerp & Implementatie Gids

Klokken zijn fundamenteel voor het bouwen van digitale circuits omdat ze verschillende blokken in sync met elkaar laten werken.

Eigenschappen van een klok

De sleuteleigenschappen van een digitale klok zijn de frequentie die de klokperiode bepaalt, de duty cycle en de klokfase in relatie tot andere klokken.

Klokperiode

De frequentie aangeeft hoeveel cycli in een bepaalde tijdsperiode gevonden kunnen worden. De klokperiode is dus de tijd die nodig is om 1 cyclus te voltooien.

Duty Cycle

De hoeveelheid tijd dat de klok hoog is ten opzichte van de periode definieert de duty cycle.

Klokfase

Als één cyclus van een klok bekeken kan worden als een volledige cirkel met 360 graden, kan een andere klok relatief op een andere plaats in de cirkel geplaatst worden die een andere fase inneemt. Bijvoorbeeld, een andere klok met dezelfde periode die naar rechts verschoven is met 1/4e van de periode kan gezegd worden op 90 graden faseverschil te zitten.

Verilog Clock Generator

Simulaties moeten opereren op een gegeven timescale met een beperkte precisie zoals gespecificeerd door de timescale-directive. Het is daarom belangrijk dat de precisie van de timescale goed genoeg is om een klokperiode weer te geven. Als de frequentie van de klok ingesteld is op 640000 kHz, is de klokperiode 1.5625 ns waarvoor een timescale-precisie van 1ps niet voldoet omdat er een extra decimaal te vertegenwoordigen is. De simulatie zal het laatste cijfer afronden om in de 3-cijferige timescale-precisie te passen. Dit verhoogt de klokperiode naar 1.563 wat eigenlijk 639795 kHz vertegenwoordigt!

De volgende Verilog clock-generator-module heeft drie parameters om de drie verschillende eigenschappen aan te passen. De module heeft een input enable die de klok uitschakelt en inschakelt zoals vereist. Wanneer meerdere klokken gecontroleerd worden door een gemeenschappelijk enable-signaal, kunnen ze relatief gemakkelijk gefaseerd worden.

\`timescale 1ns/1ps
module clock_gen (
  input enable,
  output reg clk
);
  parameter FREQ = 100000; // in kHz
  parameter PHASE = 0;     // in graden
  parameter DUTY = 50;     // in percentage

  real clk_pd = 1.0/(FREQ * 1e3) * 1e9; // omrekenen naar 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

  // Initialiseer variabelen op nul
  initial begin
    clk <= 0;
    start_clk <= 0;
  end

  // Wanneer klok ingeschakeld, vertraag het sturen van de klok naar één
  // om het fase-effect te bereiken. start_dly is geconfigureerd naar
  // de juiste vertraging voor de geconfigureerde fase. Wanneer enable 0 is,
  // laat genoeg tijd om de huidige klokperiode te voltooien
  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

  // Bereik duty cycle door een scheef klok on/off tijd en laat dit
  // lopen zolang de klokken aanstaan.
  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

Testbench met verschillende klokfrequenties

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

Simulatie-log

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

Testbench met verschillende klokfasen

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

Simulatie-log

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

Testbench met verschillende duty cycles

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

Simulatie-log

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 toggelen om klokken te starten/stoppen

De golfvorm hieronder toont dat klokken stoppen wanneer enable laag is en starten wanneer enable hoog gezet wordt.

Verilog

  1. Verilog beheersen: Complete tutorial voor digitale schakelingontwerp
  2. Verilog concatenatie beheersen: Een praktische gids
  3. Verilog-toewijzingen begrijpen: types, syntax en best practices
  4. Verilog Blocking vs. Non-Blocking: belangrijkste verschillen uitgelegd
  5. Verilog-functies beheersen voor efficiënt RTL-ontwerp
  6. Verilog Tasks begrijpen: Functions vs Tasks, Syntax en Gebruik
  7. Verilog Math Functions beheersen voor efficiënt Hardware-ontwerp
  8. Verilog $timeformat beheersen: Precisie en Weergave-controle
  9. Verilog Timescales begrijpen en printen in elke Scope
  10. Verilog File I/O onder de knie: Openen, Lezen, Schrijven en Sluiten
  11. Beginner's Guide to Verilog: Hello World Voorbeeld