산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> verilog

Verilog 클럭 생성기: 설계 및 구현 가이드

클럭은 서로 다른 블록들이 서로 동기화될 수 있게 하므로 디지털 회로 구축의 기초입니다.

클럭의 속성

디지털 클럭의 핵심 속성은 주파수(frequency)(클럭 주기 결정), 듀티 사이클(duty cycle), 다른 클럭과의 관계에서 클럭 위상(phase)입니다.

클럭 주기

주파수는 특정 시간 동안 몇 사이클이 있는지를 나타냅니다. 따라서 클럭 주기는 1 사이클을 완료하는 데 걸리는 시간입니다.

클럭 듀티 사이클

클럭이 하이 상태인 시간이 주기 대비 몇 퍼센트인지 정의합니다.

클럭 위상

한 클럭 주기를 360도 원으로 볼 때, 다른 클럭은 원의 다른 위치에 상대적으로 배치되어 다른 위상을 가질 수 있습니다. 예를 들어, 같은 주기의 다른 클럭이 주기의 1/4만큼 오른쪽으로 이동하면 90도 위상 차이라고 할 수 있습니다.

Verilog 클럭 생성기

시뮬레이션은 timescale 지시자로 지정된 제한된 정밀도를 가진 주어진 타임스케일에서 작동해야 합니다. 따라서 timescale 정밀도가 클럭 주기를 표현하기에 충분히 좋은지 확인하는 것이 중요합니다. 예를 들어, 클럭 주파수가 640000 kHz로 설정되면 클럭 주기는 1.5625 ns가 되는데, 1ps timescale 정밀도로는 추가 소수점을 표현할 수 없어 시뮬레이션이 마지막 자리를 반올림하여 3자리 timescale 정밀도에 맞춥니다. 이로 인해 클럭 주기가 1.563으로 늘어나 실제로는 639795 kHz가 됩니다!

다음 Verilog 클럭 생성기 모듈은 위에서 논의한 세 가지 속성을 조정하는 세 가지 파라미터를 가집니다. 모듈은 클럭을 필요에 따라 비활성화/활성화할 수 있는 입력 enable을 가집니다. 여러 클럭이 공통 enable 신호로 제어되면 상대적 위상을 쉽게 맞출 수 있습니다.

`timescale 1ns/1ps
module clock_gen (
  input enable,
  output reg clk
);
  parameter FREQ = 100000; // kHz 단위
  parameter PHASE = 0;     // 도(degree) 단위
  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

  // 변수들을 0으로 초기화
  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

  // 듀티 사이클을 비대칭 클럭 on/off 시간으로 달성하고
  // 클럭이 켜진 동안 계속 실행
  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 결합(Concatenation) & 복제(Replication) 연산자 실전 가이드
  3. Verilog 할당문 이해: 유형, 문법, 모범 사례
  4. Verilog 차단 vs 비차단 할당: 핵심 차이점 완벽 이해
  5. Verilog 함수 마스터하기: 효율적인 RTL 설계를 위한 활용법
  6. Verilog 태스크 이해: 함수와의 차이점, 문법, 활용법
  7. Verilog 수학 함수 마스터하기: 효율적인 하드웨어 설계를 위한 활용
  8. Verilog $timeformat 마스터하기: 정밀도 및 표시 제어
  9. 모든 범위에서 Verilog Timescale 이해 및 출력하기
  10. Verilog 파일 I/O 마스터하기: 열기, 읽기, 쓰기, 닫기