0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ずっとFPGA初心者(その12:関数)

Posted at

VHDLで関数を使う

今回のお題は、VHDLで関数を扱うもの。

環境

その1からずっとOdyssey MAX10 FPGA Eval KitおよびQuartus利用。

サンプル

LEDを用いてストップウォッチを実現

ボタン0(BTN0)押下でスタート、再押下でラップ、再押下でストップ(リセット)する。
 STOP -> RUNNING -> LAP (RUNNING) -> STOP -> RUNNING -> ....
という状態遷移(繰り返し)となる。ボタン1(BTN1)が押下されていないときには、スタートからの経過時間(秒)をLED表示、ボタン1が押下されたときには、ラップ時間をLED表示するものとする。

関数の利用

スタートからの経過時間(秒)およびラップ時間(秒)をLEDで表現するところに関数を用いる。表現方法としては、前回その11の秒カウンタと同じ方式を用いる。なお、あえて関数化する必要はないレベルではあるが、単純な例の方が関数を説明する上でわかりやすいであろう。

functionとprocedure

関数化の方法として、VHDLには、functionとprocedureとがあるらしい。今回はprocedureを利用。今回、VHDLの関数について参考にしたサイトは次のとおり。

VHDLコード

ライブラリおよび信号定義

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all; -- necessary for conv_std_logic_vector

entity ProcTest is
  port (
    CLK, BTN0, BTN1 : in  std_logic;
    LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7 : out std_logic);
end;

ここは自明なので、説明省略。

関数部分

architecture RTL of ProcTest is

procedure p_Disp (
  constant p_NUM : in  integer;
  signal p_OUT : out std_logic_vector(7 downto 0) ) is
  begin
  p_OUT <= not conv_std_logic_vector(p_NUM,8);
end p_Disp;

procedure利用。次の引数がある。

  • p_NUM:入力 - LEDで表現したい数値
  • p_OUT;出力 - ビット変換した結果(呼び出し側でLEDに代入)
    conv_std_logic_vector()を使って、数値をビット値へ変換する。

変数定義

signal LED: std_logic_vector(7 downto 0) := "11111111"; -- Off
constant CYCLE : integer := 50000000;
signal CNT : integer range 0 to CYCLE-1;
signal SEC : integer := 0;
signal LAP : integer := 0;
signal FLAG: integer := 0;  -- 0:Stop 1:Start->Running 2:Lap(&Running) 
  • LED:LED用のビット列(初期値OFF、負論理)
  • CYCLE:1秒(50MHz)
  • CNT:クロック用カウンタ
  • SEC:秒カウンタ
  • LAP:ラップ値
  • FLAG:状態遷移フラグ(0:停止 → 1:実行中 → 2:ラップかつ実行中 → 0 → 1 → 2 → 0 ...)

メインルーチン

begin
  LED0 <= LED(0); LED1 <= LED(1); LED2 <= LED(2); LED3 <= LED(3);  -- ①
  LED4 <= LED(4); LED5 <= LED(5); LED6 <= LED(6); LED7 <= LED(7);  -- ②

  process (BTN0)  -- Removal of chattering should be considered -- ③
  begin
    if (BTN0'event and BTN0='0') then
      if (FLAG = 0) then     -- Stop
        FLAG <= 1;           -- to Running
      elsif (FLAG = 1) then  -- Running
        FLAG <= 2;
        LAP <= SEC;          -- Record Lap  -- ④
      else  -- FLAG = 2      -- Running    
        FLAG <= 0;           -- to Stop
        LAP <= 0;            -- Init Lap
      end if;
    end if;
  end process;

  process (SEC, BTN1)  -- ⑤
  begin
--    if (BTN1'event and BTN1='0') then -- NG -- ⑥ 文法エラー
    if (BTN1='0') then
      p_Disp(LAP, LED);  -- ⑦
    else
      p_Disp(SEC, LED);  -- ⑧
    end if;
  end process;

  process (CLK)  -- ⑨
  begin
    if (FLAG = 1 or FLAG = 2) then  -- Runinng -- ⑩
      if (rising_edge(CLK)) then
        if (CNT = CYCLE-1) then
          CNT <= 0;
	       SEC <= SEC+1;
        else
          CNT <= CNT+1;
        end if;
      end if;
    else -- FLAG = 0 (Stop) -- ⑪
      CNT <= 0;
      SEC <= 0;
     end if;
  end process;
end RTL;
  • ①、②、③、⑤、⑨:同時に処理される
  • ①、②:LED用ビット列をLED信号に代入
  • ③:BTN0押下毎の状態遷移、実行中に押下されると、秒カウンタをLAPに代入(④)(チャタリングは未考慮)
  • ⑤:LEDによる数値表示を関数「p_Disp」により毎秒実行、押下時はLAP表示(⑦)、非押下時は経過秒SEC表示(⑧)
  • ⑥:この直後の行の代わりにこの行を用いると文法エラーとなる
  • ⑨:実行中はクロックカウンタおよび秒カウンタインクリメント(⑩)、非実行中は両カウンタ初期化(⑪)

ピンアサイン

スクリーンショット 2021-06-06 16.38.04.png

実験

BTN1押下

LAPを表示(ここでは5)。

BTN1非押下

SEC(経過秒)を表示(ここでは4)

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?