1500円ZYNQ基板でFPGAプログラミング大全Xilinx編(第2版)の実習 2-2 可変速LED点滅回路

#はじめに
前回の続きです。

1500円 ZYNQ 基板 EBAZ4205で、FPGAプログラミング大全Xilinx編(第2版)の
課題2-2 "LED点滅回路にプッシュスイッチ入力を追加" をやってみます。


#関連ファイルのダウンロード
ソースファイル一式を、FPGAプログラミング大全Xilinx編(第2版) サポートサイトから取ってきます。
https://www.shuwasystem.co.jp/support/7980html/6326.html

XilinxFPGA_SE.zip を解凍して、\Cora_Z7-10\dai2-3sho\blinkspeed フォルダをデスクトップに展開します。

#制約ファイル(blinkspeed.xdc)の変更
Cora Z7-10 と EBAZ4205 では、FPGA のピンと、LED やスイッチの接続が違っているため、制約ファイル(blinkspeed.xdc)を変更します。
既存のポート名に対応する FPGA のピン番号を修正します。
変更点は、下記の通りです。

>クロック入力
> Cora Z7-10:H16 (125 MHz) → EBAZ4205:N18 (33.333 MHz)
> Cora Z7-10:クロック周期 8ns → EBAZ4205:クロック周期 30ns
>
>スイッチ入力 (RESET)
> Cora Z7-10:D19 (BTN1) → EBAZ4205:V13 (U67 に付けたスイッチ - 基板端側)
>
>LED出力
> Cora Z7-10:N15 (赤) → EBAZ4205:W14 (赤)
> Cora Z7-10:G17 (緑) → EBAZ4205:W13 (緑)
> Cora Z7-10:L15 (青) → EBAZ4205:U12 (NCピン - 出力しても何も起きない)
>
>スイッチ入力 (点滅速度UP)
> Cora Z7-10:D20 (BTN0) → EBAZ4205:V15 (U68 に付けたスイッチ - 基板内側)

```blinkspeed.xdc
## EBAZ4205 constraints file
## chapter: 2
## project: blinkspeed

#Clock signal
set_property -dict { PACKAGE_PIN N18   IOSTANDARD LVCMOS33 } [get_ports { CLK }];
create_clock -add -name sys_clk_pin -period 30.00 -waveform {0 4} [get_ports { CLK }];

#Reset
set_property -dict { PACKAGE_PIN V13   IOSTANDARD LVCMOS33 } [get_ports { RST }]; # BTN[1]

# RGB LEDs
set_property -dict { PACKAGE_PIN W14   IOSTANDARD LVCMOS33 } [get_ports { LED_RGB[2]  }]; # Red
set_property -dict { PACKAGE_PIN W13   IOSTANDARD LVCMOS33 } [get_ports { LED_RGB[1]  }]; # Green
set_property -dict { PACKAGE_PIN U12   IOSTANDARD LVCMOS33 } [get_ports { LED_RGB[0]  }]; # Blue

# Buttons
set_property -dict { PACKAGE_PIN V15   IOSTANDARD LVCMOS33 } [get_ports { BTN[0] }];
```

#可変速 LED 点滅回路(blinkspeed.v)の変更
Cora Z7-10 と EBAZ4205 の搭載部品の違いから、下記 3 点を変更します。
>・クロック周波数が 125 MHz → 33.333 MHz に遅くなるため、カウンタの bit 数を 27bit から 25bit へ減らす
>　⇒ カウンタ幅を cnt27[26:0] から cnt25[24:0] へ減少
>　⇒ ALL1 検出を 27'h7ffffff から 25'h1ffffff へ変更。以下、同様に 1bit づつ減らした 3 つの状態を記述。
>・LED が RGB ではなく RG しかないため、点滅パターンを変更 (LEDデコーダ)
>・LED への出力値と点灯の論理が逆なので、出力値に ~ を追加して反転で表記 (LEDデコーダ)

```blinkspeed.v
/* Copyright(C) 2020 Cobac.Net All Rights Reserved. */
/* Copyright(C) 2020 Cobac.Net All Rights Reserved. */
/* chapter: 第2章                           */
/* project: blinkspeed                      */
/* outline: LEDの点滅速度をプッシュSWで制御 */
/* modifyed by KAN573                       */

module blinkspeed (
    input               CLK,
    input               RST,
    input       [0:0]   BTN,
    output  reg [2:0]   LED_RGB
);

/* チャタリング除去回路を接続 */
wire btnon;

debounce d0 (.CLK(CLK), .RST(RST), .BTNIN(BTN), .BTNOUT(btnon));

/* 速度設定用カウンタ */
reg [1:0] speed;

always @( posedge CLK ) begin
    if ( RST )
        speed <= 2'h0;
    else if ( btnon )
        speed <= speed + 2'h1;
end

/* システムクロックを分周 */
reg [24:0] cnt25;

always @( posedge CLK ) begin
    if ( RST )
        cnt25 <= 25'h0;
    else
        cnt25 <= cnt25 + 25'h1;
end

/* LED用カウンタのイネーブルを作成 */
reg ledcnten;

always @* begin
    case ( speed )
        2'h0:   ledcnten = (cnt25      ==25'h1ffffff);
        2'h1:   ledcnten = (cnt25[23:0]==24'hffffff);
        2'h2:   ledcnten = (cnt25[22:0]==23'h7fffff);
        2'h3:   ledcnten = (cnt25[21:0]==22'h3fffff);
        default ledcnten = 1'b0;
    endcase
end

/* LED用5進カウンタ */
reg [2:0] cnt3;

always @( posedge CLK ) begin
    if ( RST )
        cnt3 <= 3'h0;
    else if ( ledcnten )
        if ( cnt3==3'd5)
            cnt3 <=3'h0;
        else
            cnt3 <= cnt3 + 3'h1;
end

/* LEDデコーダ */
always @* begin
    case ( cnt3 )
        3'd0:   LED_RGB = ~3'b100;
        3'd1:   LED_RGB = ~3'b010;
        3'd2:   LED_RGB = ~3'b110;
        3'd3:   LED_RGB = ~3'b010;
        3'd4:   LED_RGB = ~3'b100;
        3'd5:   LED_RGB = ~3'b000;
        default:LED_RGB = ~3'b000;
    endcase
end

endmodule
```

#チャタリング除去回路(debounce.v)の変更
125MHz で 40Hz = 3125000 から、33.333MHz で 40 Hz = 833333 にカウンタ分周数を変更。

```debounce.v
/* Copyright(C) 2020 Cobac.Net All Rights Reserved. */
/* chapter: 第2章                                   */
/* project: debounce                                */
/* outline: プッシュスイッチ入力のチャタリング除去  */
/* modified by KAN573                               */

module debounce (
    input       CLK,
    input       RST,
    input       BTNIN,
    output  reg BTNOUT
);

/* 33 MHzを分周し40Hzを作成 */
reg [21:0] cnt22;

wire en40hz = (cnt22==22'd833333-1);

always @( posedge CLK ) begin
    if ( RST )
        cnt22 <= 22'h0;
    else if ( en40hz )
        cnt22 <= 22'h0;
    else
        cnt22 <= cnt22 + 22'h1;
end

/* スイッチ入力をFF2個で受ける */
reg ff1, ff2;

always @( posedge CLK ) begin
    if ( RST ) begin
        ff1 <= 1'b0;
        ff2 <= 1'b0;
    end
    else if ( en40hz ) begin
        ff2 <= ff1;
        ff1 <= BTNIN;
    end
end

/* 立ち上がり検出し、FFで受ける */
wire temp = ff1 & ~ff2 & en40hz;

always @( posedge CLK ) begin
    if ( RST )
        BTNOUT <= 1'b0;
    else
        BTNOUT <= temp;
end

endmodule
```


#コンパイル
オリジナルと同じですので、大全の手順通りでよいです。

#動作確認
前回投稿したのと同じ発光パターンで LED が点滅します。
U68 に取り付けたスイッチを押すと、点滅周期が早くなります。
4回目で元の周期に戻ります

U67 に付けたスイッチがリセットボタンです。
押すと点滅周期が元に戻ります。
![4_動作確認.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/67341cc1-865c-1508-2c39-41e011d912de.jpeg)


#まとめ
2-2 可変速 LED 点滅回路の記述と動作確認について、EBAZ4205 で学習することができました。