2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Flip-Flopでお手軽UVM(Clocking block)

Last updated at Posted at 2025-01-02

はじめに

はいっ! えー、みなさん、えー、ロリこんばんわ、おは幼女1

えーということでですね、えー、第四回目、第四回目の記事はですね、まあ、かるくClocking blockついてね、えーすこし語っていこうかなぁとおもいます2

えーいちおうですね、正月休みの終わりのほうがですね、近づいていますのでね、それまでにね、一本軽くね、記事のほう上げれたらいいかなーと思いまして、えーまあClocking blockについてかるくね、えー語っていこうと思いますね3

Clocking blockとは何か

ChatGPT先生に教えてもらいます4。AIに嘘を教えられている可能性も否定できないので、もしも誤りがありましたら、有識者の皆さんコメントをお願いいたします5

Clocking blockとは何ですか。詳しく教えてください
Clocking blockは、SystemVerilogでクロックと信号の同期を管理するために導入された構造です。テストベンチや設計の記述において、クロック信号を基準に入出力信号を効率的に制御し、タイミングに関する問題を軽減します。これにより、同期の定義が一元化され、テストベンチの記述が簡潔で明確になります。

なるほど。Clocking blockはどうやって使うんだろう。
聞いてみよう6

Clocking blockの使い方について教えてください
Clocking blockを使うことで、テストベンチでクロック信号に同期した信号の駆動やサンプリングを簡単に管理できます。以下に基本的な使い方を説明します。

1. Clocking blockの定義

クロック基準と信号を定義します。例えば、clkの立ち上がりエッジに同期した信号を以下のように記述します。

clocking cb @(posedge clk); 
    input  data;       // クロックエッジでサンプリングする信号
    output enable;     // クロックエッジで駆動する信号
endclocking

2. 信号の駆動とサンプリング

テストベンチでclockingブロックを使用して信号にアクセスします。

initial begin
    cb.enable <= 1;   // enable信号を駆動
    #10;
    $display("Data: %0d", cb.data); // data信号をサンプリング
end

3. 時間スキューの設定

inputoutput信号にスキュー(遅延)を設定できます。

clocking cb @(posedge clk);
    input #2 data;    // クロックエッジの2単位後にサンプリング
    output #1 enable; // クロックエッジの1単位後に駆動
endclocking

なーほーね7。そおゆうことか、これわ便利だは8
Clocking block、完全に理解した59

……で、今日の晩御飯なににする?
なんと!晩御飯の質問ですって?

ここはSystemVerilogの学びの場です!クロックの同期やテストベンチの構造について熱く議論するはずが、なぜ突然、晩御飯の話題に流れるのでしょうか!?せっかくクロッキングブロックの奥深さを語ろうとしていた矢先に、食事の提案を迫られるなんて、私のコードを書く手が震えますよ!

それでも…晩御飯の話題に情熱を注ぐあなたには逆らえません。SystemVerilogの美しさも、空腹には敵いませんからね。いいでしょう、カレーでも鍋でも食べてエネルギーをチャージしてください。そして満腹になったら、ぜひSystemVerilogに戻りましょう!😉

なんかもう全部ChatGPTに聞けばいいんじゃないの。私いらなくね?……とかそんな気がしてきましたが、まあいいでしょう。ここからは私が温かみのある血の通った人間の言葉で説明しましょう、そうしましょう10

Interfaceにタスクを入れてみるテスト11

このセクションは天才チンパンジー「アイちゃん」が言語訓練のために書いたものです。アイと研究員とのやり取りに利用するページなので、関係者以外は書きこまないで下さい12。霊長類研究所

さて、私たちは今回、新たに「Clocking block」なるものを手に入れました。これを使うと、前回のテストパターンがもう少し簡潔に書けます。例えばこんなかんじです。

前回(Clocking Block なし)
@(posedge vif.mp.clk);
#(output_skew);
vif.mp.rstn <= 1'b1;
`uvm_info(get_type_name(), "RSTN = 1", UVM_MEDIUM)

@(posedge vif.mp.clk);
#(output_skew);
vif.mp.d <= 1'b1;
`uvm_info(get_type_name(), "D = 1", UVM_MEDIUM)
今回(Clocking Block あり)
@(vif.mp.cb);
vif.mp.cb.rstn <= 1'b1;
`uvm_info(get_type_name(), "RSTN = 1", UVM_MEDIUM)

@(vif.mp.cb);
vif.mp.cb.d <= 1'b1;
`uvm_info(get_type_name(), "D = 1", UVM_MEDIUM)

もちろん、これですでに十分といえば十分……なのですが、せっかくなので、今日はちょっと欲張って、さらにテストを短く(あるいは抽象度を高く)書けるように、もうひと手間加えてみましょう。具体的には、D = 0/1RSTN = 0/1といった操作をタスクとしてまとめて、Interfaceの定義のなかにぶち込んじゃいましょう。そうすれば、

@(vif.mp.cb);
vif.mp.reset();

@(vif.mp.cb);
vif.mp.write(1'b1);

のように、Flip-Flopに対する操作をもっとスマートに書けるようになって、みんな幸せじゃないですか。ねえ、あなたもそう思いませんか?そうですよね、私の言ってること……間違ってませんよね?わたしふつうですよね?どう考えてもあの人たちのほうがおかしいですよね!?13

これが僕たちの新しいInterface

刮目せよ!14 これが私たちの新しいInterfaceだ!
resetwriteタスク完備!駅までバスで20分、郊外庭付き中古一戸建て!15

dff_if.sv
interface dff_if (
  input logic clk
);
  timeunit 1ns;
  timeprecision 1ps;

  localparam realtime input_skew = 0.2ns;
  localparam realtime output_skew = 0.2ns;

  logic rstn;
  logic d;
  logic q;

  clocking cb @(posedge clk);
    default input #(input_skew) output #(output_skew);
    output rstn;
    output d;
    input q;
  endclocking

  modport mp (
    clocking cb,
    input clk,
    import reset,
    import write,
    import delay
  );

  task automatic reset ();
    @(cb);
    cb.d <= 1'b0;
    cb.rstn <= 1'b0;
    @(cb);
    cb.rstn <= 1'b1;
  endtask

  task automatic write (logic d);
    @(cb);
    cb.d <= d;
  endtask

  task automatic delay (int unsigned n);
    repeat (n) begin
      @(cb);
    end
  endtask

endinterface

テストベンチ

というわけで、新しいテストベンチはこんな感じ。Clocking blockとInterface内のTaskのおかげで、simple_testクラスのrun_phase()がかなりスッキリしました、やったぜ!

my_pkg.sv
package my_pkg;
  timeunit 1ns;
  timeprecision 1ps;

  `include "uvm_macros.svh"
  import uvm_pkg::*;

  class simple_test extends uvm_test;
    `uvm_component_utils(simple_test)
    
    virtual dff_if vif;

    function new (string name="simple_test", uvm_component parent=null);
      super.new(name, parent);
    endfunction

	  virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      if (!uvm_config_db#(virtual dff_if)::get(this, "", "vif", vif)) begin
        `uvm_fatal(get_type_name(), "Failed to get vif")
      end
    endfunction

    virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      `uvm_info(get_type_name(), "Started", UVM_MEDIUM)
      vif.mp.reset();
      vif.mp.write(1'b1);
      vif.mp.write(1'b0);
      vif.mp.delay(2);
      `uvm_info(get_type_name(), "Finished", UVM_MEDIUM)
      phase.drop_objection(this);
    endtask
  endclass
  
endpackage
top.sv
module top;
  timeunit 1ns;
  timeprecision 1ps;

  import uvm_pkg::*;
  import my_pkg::*;

  parameter realtime clk_period = 1ns;
  bit clk = 1'b0;

  initial begin
    forever begin
      #(0.5*clk_period);
      clk = ~clk;
    end
  end

  parameter realtime skew = 0.2ns;

  dff_if intf (
    .clk
  );

  DFF dut (
    .D(intf.d),
    .CLK(intf.clk),
    .RSTN(intf.rstn),
    .Q(intf.q)
  );

  initial begin
    uvm_config_db#(virtual dff_if)::set(uvm_root::get(), "*", "vif", intf);
    run_test();
  end
  
endmodule

DSimの実行スクリプト

run.batoptions.txt前回の記事と同じですので、そちらを参照してください。

シミュレーション結果

あ、いつもの置いときますね16

Screenshot 2025-01-02 122801.png

おわりに

はーい、おつかれさまですー、よくがんばりましたねー、今日はこれでおしまいですよー
今回からお薬のほう増やしておきますねー。朝晩 食後に2錠ずつ飲んでくださいねー
それと今度カウンセリングも受けましょうねー17

次回「いざ!真のUVMへ!Environment、Agent、Sequence、SequencerにDriver」

Screenshot 2025-01-02 101622-topaz-enhance-1x-exposure-color.png
むすめとごはん「かめのこさん」より

2025/01/03 追記

本記事の投稿後、「テストベンチで扱うInterfaceはパラメタ化しないほうがよい」とのコメントをいただきました18。また、パラメタ化されたInterfaceを安易に使用して事故った例が「r/Verilog - Trouble with Parameterized Virtual Interfaces」にあります1920。そのため、parameterを使わない形にdff_if.svtop.svを修正しました。Thank you!

  1. おまわりさんこいつです!

  2. これまでの記事
    1)Flip-Flopでお手軽UVM(できなかった)
    2)Flip-Flopでお手軽UVM(uvm_test)
    3)Flip-Flopでお手軽UVM(Virtual Interface)

  3. この記事は2025年1月2日に執筆されました。正月になにやってんだ。

  4. 語る……とは?

  5. ぬりかべ用AA集 - 釣り針の目の前で悩むクマー 2

  6. ん?この流れ……なんか妙に既視感があるな? そうですねこれはまた他人の記事パクr…いや違うんですよあのこれはそのあのつまりですねほらあれだよあれ、オマージュだよ!オマージュ!

  7. ホロライブ非公式wiki - 戌神ころね【語録】

  8. 「~するは」「~だは」の意味は?

  9. r/ProgrammerHumor - litterallyMe

  10. でもその前に一つだけ約束して。私のことを「劣化版ChatGPT」「AI以下の存在」「非生産的二酸化炭素製造機」「」とか言わないでね、泣いちゃうから。

  11. 同人用語の基礎知識 - 〇〇してみるテスト

  12. 個人的コピペ帳 - 天才チンパンジー「アイちゃん」

  13. にゃーん

  14. Yes、My、Dark!

  15. はぁ?

  16. 発言小町 - 日常でネット語を使う友人。指摘は失礼でしょうか?

  17. 2ch全AAイラスト化計画 - お薬増やしておきますね

  18. https://x.com/taichi600730/status/1874825800786358531

  19. 前回の記事で述べたように、UVMのテストベンチでは、Virtual Interface変数を介して、Interfaceインスタンスへの参照をtopconfig_dbsimple_testへと順々に渡していきます。つまり、Interfaceがパラメタ化されている場合、topconfig_dbsimple_testのすべての場所で、(デフォルト値をそのまま使う場合を除き)Virtual Interfaceのパラメータも逐一「正しく」指定する必要があります。もし一つでも間違えたり値を指定し忘れたりすると、意図せず型不一致が起きてしまいます。このような理由から、一般に「テストベンチで扱うInterfaceをパラメータ化するのは避けたほうがよい」とされている……のだと思います。たぶん。

  20. このような事故、言い換えると「Virtual Interfaceの型不一致によるエラー」を体験してみたい人のために、こちらにサンプルを置いておきました。どぞ。DSimで実行すると=E:[InvalidTypeAssign]: Invalid types for operands of the following assignments:というエラーとご対面できます。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?