前回、FPGA MAX10搭載基板と書き込み器製作用プリント基板の初期セットアップが完了したので、今回はLEDチカチカ回路を作ってみようと思います。
まずは、Quartus Primeを実行します。Windowsのスタートメニューの中から実行できます。
新規プロジェクトを作成します。作成ディレクトリは任意で構いませんが、日本語は使用しない方がよさそうです。プロジェクト名はFPGAにしました。私の使用しているデバイスは「10M08SAE144C8GES」のようです。シミュレーション・ツール形式は「Verilog HDL」に設定しておきます。
次にVerilog HDL Fileを作成します。そして下記のようにハードウェア言語「Verilog HDL」を入力します。
`define CYCLE_1SEC 48000000 // ------------------- // Top of the DE10_Lite_Test_001 // ------------------- module DE10_Lite_Test_001 ( input wire clk, // 48MHz Clock input wire res_n, // Reset Switch output wire [2:0] led // LED Output ); // ----------------------------- // Counter to make 1sec Period // ----------------------------- reg [31:0] counter_1sec; wire period_1sec; // always @(posedge clk, negedge res_n) begin if(~res_n) counter_1sec <= 32'h00000000; else if(period_1sec) counter_1sec <= 32'h00000000; else counter_1sec <= counter_1sec + 32'h00000001; end // assign period_1sec = (counter_1sec == (`CYCLE_1SEC - 1)); // ----------------------------- // Counter to make LED signal // ----------------------------- reg [2:0] counter_led; // always @(posedge clk, negedge res_n) begin if(~res_n) counter_led <= 3'b000; else if(period_1sec) counter_led <= counter_led + 3'b001; end // assign led = ~counter_led; // LED on by low level endmodule
「Verilog HDL」言語については後ほど詳細を調べようと思います。とりあえず動作させる事を優先します。次にTasks内の「Analysis & Synthesis」を右クリックしてStartを選択します。これは「Verilog HDL」言語の解析と合成を実行しています。構築したコードが動作するかどうかチェックして、Quartus Primeにモジュールの階層構造や信号名を認識させているようです。
次に外部端子への信号アサインを行います。メニューより[Assignments]→[Pin Planner]を選択します。
clkにPin_27を、led[2]にPIN_121、led[1]にPIN_122、led[0]にPIN_120、res_nにPIN_123を設定します。メニューより[Processing]→[Start Complication]を選択します。Tasks内からの実行など、他にも実行方法はあります。
次にMAX10版FLASHメモリにでなく、FPGA内のコンフィグレーション用のSDRAMへ書き込みます。SDRAMに書き込むので、電源を落とすと書き込みはなくなります。Tasks内のProgram Deviceを右クリックして、Openを選択します。
Add Fileより先程作成したsofファイルを選択して、Program/Configureにチェックを入れて、Startを選択します。プログレスバーが100%になれば、コンフィグ成功です。FLASHメモリに書き込む際は、pofファイルを選択して、CFM0のProgram/Configureにチェックを入れて、Startを選択します。FLASHメモリに書き込んだ場合は、電源を落として、再度起動してもLEDが光るのが確認できます。
それでは、Verilog HDLで記述したコードを分析していこうと思います。
module FPGA();~endmodule
これが大枠になるようです。括弧の中身は実際にFPGAとやり取りする引数になると思います。それでは、括弧の中身を見ていきます。
input、output,inout
これはポート宣言で、実際にMAX10に信号を送ったり、MAX10から信号をもらったりする部分になります。「input 信号名」と宣言します。
バス(デバイス間通信)の宣言もできます。「input [MSB(上位ビット):LSB(下位ビット)] 信号名」と宣言します。
上記コードではLEDデバイスと通信する為にバスの宣言を使用しています。
wire, reg
これはそれぞれネット宣言,レジスタ宣言とです。
ネット変数は、宣言ではモジュール内で使用する変数で、常にゲートや継続代入文によって値を送受信しており、送受信していない時にはハイインピーダンス状態になります。ハイインピーダンスとはようは抵抗が大きい状態なので、電流が流れない。よって、値を送受信されない状態です。
レジスタ変数は、データを保持します。
ネット型変数の信号への代入は、assign 文でのみ可能で、レジスタ変数の信号への代入は,always 文,initial 文などで可能です。
always @(ステートメント)
ステートメントには、信号名が入ります。信号名だけの時は、信号が立ち上がる時と,立ち下がる時にbegineからendの処理がされます。posedge 信号名の時は、信号が立ち上がる時、begineからendの処理がされます。negedge 信号名の時は、信号が立ち下時、begineからendの処理がされます。
beginからendの中には、よく見るif文が記載されています。if文は、resetスイッチ(SW1)が押された時(Lowの時)、period_1secが1の時に、counter_1secを0に初期化されます。その他はcounter_1secをインクリメントします。
32’h00000000は32bitの16進数で10進数の0を表します。32’h00000001は32bitの16進数で10進数の1を表します。
assign
組合せ回路を記述する時にassign 文を使用します。 assgin 文の左辺はネット型変数になります。右辺には、論理式がよく使用されますが、定数なども設定可能です。
上記コードでは、counter_1secと`CYCLE_1SEC – 1の値がイコールの時に、period_1secに1が代入されます。ここまでが、カウンタの処理になります。
LEDも使用している文法はほぼ同じです。LEDはresetスイッチ(SW1)が押された時(Lowの時)、LEDを消すために、counter_ledに0を入力、period_1secが1の時に、色を変更する為に、counter_ledをインクリメントします。assignを使用して、ledにcounter_ledの否定値を入力します。LEDはLow信号の時に光るので、led[2:0]が111の時にLEDは消えます。