リスト1は、Tang Nano 9Kに実装するお絵描きソフトの回路をVerilogHDLで表したものです。以下のGitHubのリポジトリにプロジェクトごとアップロードしていますのでご参照ください。
⇒お絵描きソフトのプロジェクトがあるGitHubのリポジトリはこちら
リストには説明の便宜上執筆時のコードに行番号を付していますが、リポジトリのソースコードが更新されると最新のコードとは行番号が異なる場合があることをご了承ください。
1: module dpad2(input rst,input clk,input [3:0]btn,output low,input Abtn,Bbtn,output [7:0]col,[7:0]row); 2: assign low=0; 3: reg [7:0]regs[7:0]; 4: reg [28:0] counter; 5: reg [2:0] x,y; 6: 7: assign col=(((counter[15:13]==y)&& (counter[21]))?1<<x:0)^(regs[counter[15:13]] ); 8: assign row = ~(1<<counter[15:13]); 9: 10: always @(posedge counter[21] or negedge rst) 11: if(rst==0) {regs[0],regs[1],regs[2],regs[3],regs[4],regs[5],regs[6],regs[7],x,y}=0; 12: else begin 13: case(btn) 14: 4'b0111: x=x+1; 15: 4'b1101: y=y+1; 16: 4'b1011: y=y-1; 17: 4'b1110: x=x-1; 18: endcase 19: if (Abtn==0) regs[y][x]=1; 20: if (Bbtn==0) regs[y][x]=0; 21: end 22: 23: always @(posedge clk) counter <= counter + 1; 24: endmodule
リスト1の1行目では、モジュール(module)名の定義を行っています。定義とはモジュールの名称とそのモジュールの入出力を設定することを意味します。モジュール名はdpad2です。
rstはリセットボタンです。1ビット長の入力として定義されています。Tang Nano 9KのUSBコネクターを左側にした場合に、コネクターの上側にある白いタクトスイッチがリセットボタンとして働くように後の処理で接続されることになります。
clkはクロックをこのモジュールに取り込む1ビット長の入力として定義されています。[3:0]btnは十字キーの4個のタクトスイッチに対応する4ビット長の入力として定義されています。
lowは1ビット長の出力として定義されています。AbtnとBbtnはそれぞれAボタン、Bボタンに接続され、1ビット長の入力として定義されています。[7:0]col、[7:0]rowはそれぞれ8ビット長の出力として定義されており、LEDドットマトリクスに接続されます。
2行目では、出力ポートして定義したlowを0とします。LOW電圧を出力しますのでGND(グランド)の代わりにこのピンを使います。3行目では8×8ビットのレジスタを用意します。プログラム言語でいえば変数のようなものです。4行目では29ビット長のレジスタをcounterとして用意します。5行目では3ビット長のレジスタをx、yとして用意します。7〜8行目は、8個のregsの値すなわち64ビット分をLEDドットマトリクスに反映させています。かつ7行目ではカーソルの位置のLEDを点滅させています。
10〜21行目で、十字キーとAボタン、Bボタンの押下に応じて、カーソル位置を示すx、yの値を更新しています。そしてAボタンが押されればregsのその位置のビットを1にしています。またBボタンが押されればそのビットを0にしています。23行目ではcounterの値をクロックの立ち上がりごとにインクリメントしています。
どうでしょう、ここではVerilogHDLの書き方の解説が目的ではないので説明は大ざっぱになりましが、C言語などの経験があればコードの意味は何となく分かるのではないでしょうか。あとコードを眺める上で大切なことは、別に行番号の若い順に実行されるわけではなく、後に書こうが先に書こうがそれで実行順が決まるわけではありません。それぞれ並列に実行されるので、そこはコンピュータ言語脳のままでこのコードを見ていると少し慣れるまでは戸惑うかもしれません。
10行目に関して補足しておきましょう。以前の書き方ではこの処理に8行ものコードを擁していましたが、今回はそれを1行で記述しています。この処理は8ビット長の出力ポートであるrowはLEDドットマトリクスのカソード側に接続されます。その行に応じたビットのみを0にすればその行のLEDの8列が光るというわけです。これを目に見えない速さで繰り返すとLEDドットマトリクス全体でregsの値を映し出しているように見えるのです。それを1行で実現しているのがこのコードです。
まずcounter[15:13]はひたすら0から7を繰り返していますので、その値に応じて1を大きい桁側にシフトさせます。するとcounterの値に応じて1のある桁がずれることになります。しかし今回欲しい値は、他は1にしてターゲットの桁だけ0にしたいのでこれの否定をとります。これをrowにアサインすることでLEDドットマトリクスのカソード側のピンをスキャンする回路を実現しているのです。
Copyright © ITmedia, Inc. All Rights Reserved.