Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Verilog

Генератор тактового сигнала в Verilog: проектирование и реализация

Тактовые сигналы фундаментальны для цифровых схем — они синхронизируют разные блоки.

Свойства тактового сигнала

Ключевые свойства: частота (определяет период), скважность (duty cycle) и фаза относительно других тактовых.

Период тактового сигнала

Частота показывает, сколько циклов в единице времени. Период — время для завершения 1 цикла.

Скважность (Duty Cycle)

Доля времени, когда такт высокий, к периоду.

Фаза тактового сигнала

Один цикл — полный круг 360°. Другой такт того же периода, сдвинутый на 1/4 периода, имеет 90° разницу фаз.

Verilog генератор тактового сигнала

Симуляция работает на заданном timescale с ограниченной точностью. Важно, чтобы точность timescale позволяла представить период такта. Например, частота 640000 кГц → период 1.5625 нс. Точность 1пс не хватит (лишняя цифра), симулятор округлит до 1.563 нс → 639795 кГц.

Модуль генератора с тремя параметрами для настройки свойств. Вход enable включает/выключает такт. При общем enable для нескольких тактовых их можно легко синхронизировать по фазе.

`timescale 1ns/1ps
module clock_gen (
  input enable,
  output reg clk
);
  parameter FREQ = 100000; // кГц
  parameter PHASE = 0;     // градусы
  parameter DUTY = 50;     // проценты

  real clk_pd = 1.0/(FREQ * 1e3) * 1e9;      // период в нс
  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

  // При включении такта задерживаем запуск для фазы
  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

Simulation 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=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

Simulation Log

xcelium> run
FREQ = 100000 kHz PHASE = 0 deg DUTY = 50 % ...
FREQ = 100000 kHz PHASE = 90 deg DUTY = 50 % ...
FREQ = 100000 kHz PHASE = 180 deg DUTY = 50 % ...
FREQ = 100000 kHz PHASE = 270 deg DUTY = 50 % ...
i=0 dly=36 ... 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

Simulation Log

xcelium> run
FREQ = 100000 kHz PHASE = 0 deg DUTY = 50 % ...
FREQ = 100000 kHz PHASE = 0 deg DUTY = 25 % ...
FREQ = 100000 kHz PHASE = 0 deg DUTY = 75 % ...
FREQ = 100000 kHz PHASE = 0 deg DUTY = 90 % ...
i=0 dly=36 ... i=9 dly=13
Simulation complete via $finish(1) at time 1110 NS + 0

Переключение enable для запуска/остановки тактов

Волна ниже показывает: такты остановлены при enable=0, запущены при enable=1.

Verilog

  1. Освоение Verilog: полное руководство по проектированию цифровых схем
  2. Освоение конкатенации в Verilog: практическое руководство
  3. Понимание назначений в Verilog: типы, синтаксис и лучшие практики
  4. Блокирующие и неблокирующие назначения в Verilog: ключевые различия
  5. Мастерство функций в Verilog для эффективного RTL дизайна
  6. Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение
  7. Мастерство математических функций Verilog для эффективного аппаратного дизайна
  8. Мастерство $timeformat в Verilog: точность и контроль отображения времени
  9. Понимание и печать timescale в Verilog в любой области видимости
  10. Работа с файлами в Verilog: открытие, чтение, запись и закрытие