FPGAでミュージックシーケンサーを作る:注目デバイスで組み込み開発をアップグレード(20)(2/3 ページ)
注目デバイスの活用で組み込み開発の幅を広げることが狙いの本連載。第20回は、筆者が独断と妄想に駆られて作ってみたFPGAで制御するミュージックシーケンサーを紹介する。
仕組み
図3はミュージックシーケンサーの内部構造を示したものです。
オシレーター(発振装置)を8つ用意します。OSC_0からOSC_7がそれに当たります。それぞれのオシレーターが、LEDドットマトリクスの中で演奏を指定する低い方のラから高い方のラまでの8つの音階に対応します。いわゆる最下位ビット側がOSC_0に対応し、最上位ビット側がOSC_7に対応します。それらのオシレーターに対応する音階は以下の通りです。ちなみ今回のミュージックシーケンサーでは、オシレーターが出力できる波形は矩形波のみです。
cnt[0] 低いラ cnt[1] シ cnt[2] ド cnt[3] レ cnt[4] ミ cnt[5] ファ cnt[6] ソ cnt[7] 高いラ
各オシレーターの出力はミキサー(mixer)で統合されてRC回路で波形整形を行い出力します。RC回路はTang Nano 9Kを搭載しているブレッドボード上で組み立てます。イヤフォン程度であれば十分駆動できる出力です。ちなみに筆者はこの出力をギターアンプにつないで実験しています。
演奏ステップの実行はカウンタ(counter)とデコード回路(decoder)で実現しています。27ビットのカウンタを用意しており、27MHzのクロックでカウントアップします。カウンタの24〜26ビット目の3ビットを用いて8ステップを制御します。
また、ミキサーもカウンタの1〜3ビット目の3ビットを用いて8チャネルの入力を27MHzの2分の1の速さで切り替えています。
ミュージックシーケンサーを実現するためのHDLコード
リスト1は、このミュージックシーケンサーを実現するためにdpad2のコードに追加した部分です。VerilogHDLで記述しています。dpad2のモジュールの中に記述しています。コード全体をご覧になりたい方はリポジトリにアップしておきますのでそちらを参照してください。
⇒ミュージックシーケンサーのプロジェクトがあるGitHubのリポジトリはこちら
コード全体でも45行程度ですので、内部構成図を参考にすれば読むのにそれほど苦労することはないでしょう。なお、リストには説明の便宜上執筆時のコードに行番号を付していますが、リポジトリのソースコードが更新されると最新のコードとは行番号が異なる場合があることをご了承ください。
29: reg [15:0] cnt[7:0]; 30: wire[7:0] mixer; 31: wire[2:0] j; 32: wire[15:0] frq[7:0]; 33: assign frq[0]=61364; // 27000000/440; // A 34: assign frq[1]=54656; // 27000000/494; // B 35: assign frq[2]=51625; // 27000000/523; // C 36: assign frq[3]=45997; // 27000000/587; // D 37: assign frq[4]=40971; // 27000000/659; // E 38: assign frq[5]=38682; // 27000000/698; // F 39: assign frq[6]=34439; // 27000000/784; // G 40: assign frq[7]=30682; // 27000000/880; // A 41: integer k; 42: assign j = counter[6:4]; 43: always @(posedge clk) for (k=0;k<16;k=k+1) if (cnt[k]==frq[k])cnt[k]=0;else cnt[k]=cnt[k]+1; 44: assign mixer = ((regs[counter[27:24]]&(1<<j))!=0)?cnt[j][(j==7)?14:15]:0; 45: assign Vin = (btn3==0)?mixer[counter[3:1]]:0;
29行目では、発振周波数を決定するための16ビット長のレジスタを8個用意します。30行目は、ミキサーの8本の入力ポートを用意しています。31行目では、カウンタの4〜6ビット目の値を“j”一文字で代用するための定義です。32行目では、16ビット長のワイヤを8個確保しています。これは8つの音階を作るために必要な値を格納するためのエリアです。
33〜40行目は、先ほど定義した8個のワイヤに必要な値を入れています。例えば、33行目は440Hzの「低いラ」の周波数の矩形を生成するための値を入れています。61364という値が入っていますが、これはFPGAのシステムクロックである27MHzを440で割った値になります。
41行目では、43行目のfor文で用いる変数kを宣言しています。42行目では、31行目で定義したjにカウンタの4〜6ビット目までを定義しています。 43行目では8つの音階を生成しています。44行目では、16ステップを約1.2秒の間隔で順次切り替えています。45行目では、8個の音源を27MHzの半分の速さで切り替えています。
Copyright © ITmedia, Inc. All Rights Reserved.