@+id/proelbtn

nop, nop, nop, nop...

Verilog HDLで簡単な論理回路を組む。

Verilog HDLは簡単っぽさそうですがそれでも慣れるために練習。

回路の仕様

KEY[3]のネガティブエッジで、カウンタがインクリメントされ、RESETのネガティブエッジでカウンタがリセットされる。

カウンタが0の時、LED[3:0]にはSW[8:5] AND SW[3:0]が代入される。 カウンタが1の時、LED[3:0]にはSW[8:5] OR SW[3:0]が代入される。 カウンタが2の時、LED[3:0]にはSW[8:5] XOR SW[3:0]が代入される。 カウンタが3の時、LED[3:0]にはSW[3:0]をビット反転させたものが代入される。

コード

module logical_sample (RESET, KEY, SW, LED);
    input RESET;
    input[3:0] KEY;
    input[9:0] SW;
    output[9:0] LED;
    
    reg[3:0] val;
    reg[1:0] counter;

    always @(negedge KEY[3] or negedge RESET)
        begin
            if(RESET == 1'b0) counter <= 2'b00;
            else
                begin
                    counter <= counter + 1;
                end
                
            case (counter)
                2'b00: val = SW[8:5] & SW[3:0];
                2'b01: val = SW[8:5] | SW[3:0];
                2'b10: val = SW[8:5] ^ SW[3:0];
                2'b11: val = ~SW[3:0];
            endcase
        end
        
    assign LED[6:5] = counter;
    assign LED[3:0] = val;
endmodule

各部分の説明

1行目

module logical_sample (RESET, KEY, SW, LED);

moduleの宣言です。きっとトップレベルのモジュールは評価ボードのペリフェラルFPGA内のポートの架け橋にしたほうがよさそうなので、評価ボード上にあるRESETスイッチやKEYなどといったものを宣言しています。

2~5行目

 input RESET;
    input[3:0] KEY;
    input[9:0] SW;
    output[9:0] LED;

評価ボード上にある入出力のポートと1対1で対応できるように型を宣言しておきます。

6~7行目

 reg[3:0] val;
    reg[1:0] counter;

内部で保持しておきたい値の宣言です。内部で保持する値はreg宣言しておいてます。

8~24行目

 always @(negedge KEY[3] or negedge RESET)
        begin
            if(RESET == 1'b0) counter <= 2'b00;
            else
                begin
                    counter <= counter + 1;
                end
                
            case (counter)
                2'b00: val = SW[8:5] & SW[3:0];
                2'b01: val = SW[8:5] | SW[3:0];
                2'b10: val = SW[8:5] ^ SW[3:0];
                2'b11: val = ~SW[3:0];
            endcase
        end

ここが処理の大部分を占めていますね。always @(cond) begin ~ endでcondが成立するときに~の部分の処理を実行します。今回はKEY[3]がH->L、もしくはRESETがH->Lの時に実行されます。ポジティブエッジにしたいならnegedgeの代わりにL->HにすればOKです。

そして処理の中身です。RESETがLならcounterに0を代入して、そうでないならcounterをインクリメントします。2'b00というのは2bitで値が2進数で00という意味です。8bitで値が16進数でAFならば8'hAFとなります。まぁ、適宜調べてください。リファレンスじゃないので、、、

そして、その値を見てそれぞれの計算結果をvalに代入します。

26~27行目

 assign LED[6:5] = counter;
    assign LED[3:0] = val;

LED[6:5]とcounterを紐付けます。代入と言うより、wireとoutputを紐付ける処理な気がする。

動いてる感じ

DE0-CVを買ったのでLチカまで進めてみた。

経緯

某キャンプで「独自CPU開発で学ぶコンピュータのしくみ」という本を貰ったり、学校の授業でコンピュータアーキテクチャの本を使っていたりするので、ついにFPGAを購入してしまった。

www.amazon.co.jp

もともと、某大学のCPU実験がすごく羨ましくて購入を考えてはいたけど、そこそこの金額なので躊躇していた。今回、私は以下の商品を購入した。

www.marutsu.co.jp

開発環境の構築までを簡単にまとめておく。

対象

ryoga@Sagiri ~
(*'-')/ < uname -a
Linux Sagiri 4.10.0-37-generic #41-Ubuntu SMP Fri Oct 6 20:20:37 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

ryoga@Sagiri ~
(*'-')/ < cat /etc/os-release                  
NAME="Ubuntu"
VERSION="17.04 (Zesty Zapus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 17.04"
VERSION_ID="17.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=zesty
UBUNTU_CODENAME=zesty

開発環境の構築

必要なソフトウェアのダウンロード

DE0-CVを購入すると分かるが、ボードの上に取り付けられた保護用のアクリルボードの上に必要なソフトウェアのリンクが書いてある。

www.terasic.com.tw

このサイトから、QuartusとDE0-CV User Manualをダウンロードしておく。DE0-CVに乗っているFPGAはCyclone Vなので、Quartus Prime software Lite editionで大丈夫です。

ダウンロードが終わったらQuartusのインストールをする。

Lチカするまでの流れ

他のサイトにすごい有用な解説があるので大体はこっちを見るほうがいいと思う。ただ、そのサイトはWindowsでのお話なので、少し足りない部分を説明する。

DE0ボードを使った初めてのVerilog - My Tips

  • Device Nameを選択する所があるが、「5CEBA4F23C7」になる。
  • KEY3を入力に使うなら「PIN_M6」、LEDR9を出力に使うなら「PIN_L1」を指定する必要がある。

使用したソースコードは以下のようになる。

module led_blink (
    input sw1,
    output led
);

assign led = sw1;

endmodule