VHDL: RTLとは
2026/06/28

ハードウェアは常に動作する

  • HDLで記述するのはデジタル回路です。デジタル回路はハードウェアとして実装する想定のため、これらの回路は常に動作します。

  • ちょっとピンと来ませんね。ソフトウェアのケースと比較してみましょう。例えば下記Pythonコードの一部を見て下さい。
    a = int(input()) # [0]↓
    b = a + 5        # [1]↓
    c = b - 2        # [2]↓
    
  • メモリ上に置かれたプログラムのステートメントが上から順次実行されていきます。裏側ではCPUがクロックサイクルに合わせて記述を順番に実行しています。

  • では、HDLで記述したデジタル回路はどうでしょうか。
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity sample is
      port (
          i_a : in std_logic_vector(3 downto 0);
          o_c : out std_logic_vector(3 downto 0)
      );
    end sample;
    
    architecture RTL of sample is
      signal a : unsigned(3 downto 0);
      signal b : unsigned(3 downto 0);
      signal c : unsigned(3 downto 0);
    begin
      a <= unsigned(i_a);
      b <= a + 5;
      c <= b - 2;
    
      o_c <= std_logic_vector(c);
    end RTL;
    
  • 論理記述部を見ると変わらないように見えますね。でも、下記は常に実行されています。
    begin
      a <= unsigned(i_a);
      b <= a + 5;
      c <= b - 2;
    
  • タイミングチャートで書くと下記のような違いになります。VHDL(ハードウェア)は信号aの変化がb,cへ即時に伝搬します。つまり並列実行されます。
    Python(ソフトウェア)VHDL(ハードウェア)
    alt textalt text
  • もっと言うと、ソフトウェアの a,b,c はメモリ領域が確保された変数ですが、ハードウェアの a,b,c は単なる配線ノードです。

しかし順次記述が無いときつい

  • HDL記述は原則並列実行されますが、それだと記述しにくいものと記述できないものがあります。例えば、ある信号の値を見て異なる論理を取るケースです。
    if (b = 15) then
      c <= 0;
    else
      c <= b - 2;
    end if;
    
  • この記述は順番に解釈しないと最終的な動作が確定しません(*1)。

  • また、フリップフロップに値を記憶させる場合もそうです。クロックが入って値を取り込みますが、そのデータが保持されていることを意味する記述は並列実行文で書けません。

  • そのため、VHDLでは内部を順次記述として解釈するブロックを定義できます。それが process文です。
    process(b) begin
      if (b = 15) then
          c <= 0;
      else
          c <= b - 2;
    end process;
    
  • このprocessブロック自身は、processの外にある他の記述と同様に並列実行されますが、内部は順次記述として解釈されます。これによって複雑な論理や記憶素子を記述することができるのです。

  • 上記例の選択文の記述が使えれば RTL として、ほぼ全ての論理を書くことが可能となります。

  • ちなみにfor文を書くことはテストベンチ以外で滅多にありません。for文のループ回数分ハードウェアを置くことになるからです。

例えばフリップフロップを書く

  • ではフリップフロップ(D-FF)を書いてみましょう。rst_nで非同期リセットし、clkでdの値を取り込みます。尚dは4bitです。そのため下記は4bitのD-FFです。
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity sample is
      port (
          clk : in std_logic;
          rst_n: in std_logic;
          d : in std_logic_vector(3 downto 0);
          q : out std_logic_vector(3 downto 0)
      );
    end sample;
    
    architecture RTL of sample is
      signal r_q : std_logic_vector(3 downto 0);
    begin
    
      process(clk, rst_n) begin
          if (rst_n = '0') then
              r_q <= "0000";
          elsif rising_edge(clk) then 
              r_q <= d;
          end if;
      end process;
    
      q <= r_q;
    
    end RTL;
    
  • 簡単ですね。clkとrst_nを見て、rst_n=0ならリセット、そうでなけばclkの立ち上がりエッジ(rising_edge(clk))でdを取り込みです。

ここでRTLとは

  • 結局デジタル回路は並列記述相当部で値が決まる組み合わせ論理と、その値をprocess文で記述したレジスタで記憶して利用する構成になります。

  • つまり構造的には、下記3つを結びつけたものになります。
    • 入出力ポート
    • 組合せ論理
    • レジスタ

  • そうです。レジスタの間を論理が渡っているだけなんです。これでデジタル回路は書けてしまう。だから RTL(Register Transfer Level) と呼ぶわけです。

後は具体例を見ていくだけ

  • process文の意味と、RTL記述の意味が結びつけば、あとは具体例を見て小技を積んでいくだけになります。

  • 次回以降は具体例と、テストベンチ(順次実行だから当然process文)を扱っていきます。

(*1)VHDL-2008では3項演算子相当記述が導入されています。実は書けます。

Copyright(C) 2026 Altmo
本HPについて