6
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?

Hardware Description LanguageAdvent Calendar 2024

Day 24

Verylの(自分が提案・実装した)便利機能を紹介する

Last updated at Posted at 2024-12-23

Verylの(自分が提案・実装した)便利機能を紹介する

Verylは新興のHDLです。開発初期から機能の提案や実装などで、協力させていただいております。石谷が提案したVerylの便利機能を紹介したいと思います。

clock/reset

RTL設計においてクロック・リセットは特別な信号ですが、従来のHDLにはそれらを特別扱いする機能は無く、通常の信号として扱われます。ですので、順序回路を記述する際は、毎度毎度、クロック・リセットを指定する必要があり、非常に面倒です。

always_ff @(posedge i_clk, negedge i_rst_n) begin
  if (!i_rst_n) begin
  end else begin
  end
end

always_ff @(posedge i_clk, negedge i_rst_n) begin
  if (!i_rst_n) begin
  end else begin
  end
end

また、クロック・リセット以外の信号も指定できるので、バグの元になりえます。

VerylはRTL設計に特化したHDLなので、クロック・リセットを表す特別の型として、clock/reset型が導入されています。これらの型を導入することで、Verylコンパイラはどの信号がクロック・リセットかを簡単に判別できるようになり、モジュールに入力されるクロック・リセットが1組しかない場合、always_ffでクロック・リセットの指定を省略することができます。

元のVeryl
module ModuleA (
  i_clk: input  clock,
  i_rst: input  reset,
  i_d  : input  logic,
  o_d  : output logic,
) {
  var d: logic;

  assign o_d = d;

  // クロック・リセットを指定しなくても良い
  always_ff {
    if_reset {
      d = 0;
    } else {
      d = i_d;
    }
  }
}

Verylコンパイラはi_clk/i_rstがクロック・リセットだと判別できるので、SystemVerilog生成時にこれらの信号をalways_ff文に自動的に挿入します。

生成されたSystemVerilog
module project_ModuleA (
    input  logic i_clk,
    input  logic i_rst,
    input  logic i_d  ,
    output logic o_d  
);
    logic d;

    always_comb o_d = d;

    always_ff @ (posedge i_clk, negedge i_rst) begin
        if (!i_rst) begin
            d <= 0;
        end else begin
            d <= i_d;
        end
    end
endmodule

複数のクロック・リセットが入力されている場合、クロック境界を跨ぐ際に適切な処理ができていないと、重大なバグに繋がります。この種の問題の検出には、高価なEDAツールの導入が不可欠です。(自分が導入したわけではないですが)Verylでは、ある信号がどのクロックドメインに所属するかを指定することができるので、意図しないクロック境界跨ぎを検出することができます。

image.png

リセットの抽象化

リセットの記述は、ASCIでは非同期リセット/負極性、FPGAでは同期リセット/正極性で記述するのが良いとされています。しかし、この両方に適応した記述を従来のHDLで記述することは非常に困難です。

ASICの場合
always_ff @(posedge i_clk, negedge i_rst_n) begin
  if (!i_rst_n) begin
  end else begin
  end
end
FPGAの場合
always_ff @(posedge i_clk) begin
  if (i_rst) begin
  end else begin
  end
end

しかし、Verylでは、reset型とリセット時の動作を記述するif_resetの導入により、リセットの極性および同期・非同期は隠匿され、SystemVerilogコード生成時に選択できるようになっています。つまり、以下のVerylコードから対象に適したリセット論理を持つSystemVerilogコードが生成できると言う訳です。

Veryl
always_ff {
  if_reset {
    d = 0;
  } else {
    d = i_d;
  }
}

if式とcase

最近のオシャレ言語では、従来、制御構文であったifcaseが式として使えることが多いです。文中で同じ変数に代入する場合、これらの構文を式として使えると、代入が一か所だけになって、(ちょっとだけ)記述を簡略化できます。
例えば、カウンターの記述はcase式を使うと、以下の様に書くことができます。

count = case {i_up, i_down} {
  2'b10  : count + 1,
  2'b01  : count - 1,
  default: count
};

式なので、当然、以下の様にも書くこともできます。

count += case {i_up, i_down} {
  2'b10  : +1,
  2'b01  : -1,
  default: 0
};

しかし、SystemVerilogにはif式/case式は無いので、これらの記述は三項演算子を使って展開されます。

生成されたSystemVerilog
count <= ((({i_up, i_down}) ==? (2'b10)) ? (
    count + 1
) : (({i_up, i_down}) ==? (2'b01)) ? (
    count - 1
) : (
    count
));

処理系によっては、if文やcase文と違って、MUXの最適化が効かないので、合成で不利になるかもしれません。

6
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
6
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?