ZYBO / IP > Clock Divider > IP作成したClock Dividerを使ってFCL_CLK0(100MHz)を1Hzに分周してみた

```txt:動作環境
Vivado 2015.4 on Windows 8.1 pro (64bit)
DIGILENT ZYBO
```

## 概要

### やろうとしていること

http://qiita.com/7of9/items/ec1a0048e69e74adc39a
にてVHDLによるCLock Dividerを実装できた。

http://zynqhowto.blogspot.jp/2014/03/blog-post.html
のLab2にてそのClock DivierをIP作成して、Add IPしたデザインが紹介されている (Zedboard使用)。

こちらはZYBOなのでピンなどが変わる。ZYBOのPS CLKのピンは不明なので、FCL_CLK0から分周して1Hzを作ることにした。

### FCLK_CLK0の周波数と分周

Block DesignのRe-customize IPのClock Configuretion > Basic Clocking > PL Fabric Clocks > FCLK_CLK0に100MHzの記載がある。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/3ab92d26-37ab-30fa-b95a-be616f3dec54.png)


100MHzを1HZにするには10000 0000で分周する必要がある。ビット数は2のべき乗から考慮してlog2(10000 0000)=26.5の幅が必要。

ぎりぎりの幅(27)でいいか未消化なので29ビットとして後述の実装をした。

## IPの作成 on Vivado

### VHDL実装

VivadoでIPを作成する。
プロジェクト名は以下のようにして、C:\ZyboDev\以下に置いた。

- 160716_ClockDivider

途中までは http://qiita.com/7of9/items/ec1a0048e69e74adc39a と同じだが、Run Simulationはしない (divide がconstantでなくなるため)。

http://zynqhowto.blogspot.jp/2014/03/blog-post.html のLab2.pdfを参考に、VHDLファイルを以下のように変更した。
divide_value をstd_logic_vector()で定義して、Block Designで分周を変更できるようにしている。
ここで`divide_value : in std_logic_vector(28 downto 0);`として前述の29ビットの幅を確保している。

```UniClkDiv.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity clk_gen is
port(   Clk : in std_logic;
        divide_value : in std_logic_vector(28 downto 0);
        Clk_mod : out std_logic        
        );
end clk_gen;

architecture Behavioral of clk_gen is
    signal counter : integer := 0;
    signal divide : integer;
begin
    divide <= to_integer(unsigned(divide_value));

    process(Clk)
    begin
        if( rising_edge(Clk) ) then
            if(counter < divide/2 - 1) then
                counter <= counter + 1;
                Clk_mod <= '1';
            elsif(counter < divide - 1) then
                counter <= counter + 1;
                Clk_mod <= '0';
            else
                Clk_mod <= '1';
                counter <= 0;
            end if;
        end if;
    end process;   
end;
```

### IPの作成

上記のVHDL実装からIPを作成する。

- Tool > Create and Package IP ...
  - Create and Package New IPウィンドウが表示される
- Nextを押す
- Package your current projectを選択し、Nextを押す
- IP locationはそのまま、Include .xci filesを選択し、Nextを押す
  - 再作成時は上書きするか聞かれるので、Overwriteを選択する
- Finishを押す
  - Package IP _ clk_genというタブが表示される
- 以下の部分を変更する (名前は任意)
  - Name: myIP_clockDiv
  - Display name: myIP_clockDiv_v1_0
  - Descriptoin: myIP_clockDiv_v1_0
- Review and PackageにてPackage IPを押す

以上でIPが作成され、関連ファイルが以下のフォルダに用意される。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/487254ab-1641-49fc-7c67-49e3195dff5b.png)

こちらのプロジェクトはClose Projectで終了する。


## IPの使用

### on Vivado

- プロジェクトを作成する。名前は 160716_useClockDiv とした
- RTL Project
  - Do not specify sources at this time
- Board: ZYBOで作成
- Create Block Design
  - Design name: design_1
- Add IP: ZYNQ7 Processing System
- Run Block Automation
  - 変更せずOKを押す
- FCLK_CLK0のピンをM_AXI_GP0_ACLKのピンへ左クリックで接続
- Tool > Project Settings > IPメニュー > Repository Managerタグ
  - ＋マークを押して、前述で作成したIPの場所 ( C:\ZyboDev\160716_ClockDivider\160716_ClockDivider.srcs )を選択して追加
  - Add Repositoryウィンドウが表示される

  - Applyを押して、OKを押す
- Add IPでmyをキーワードとして検索する。myIP_clockDiv_v1_0が見つかるのでaddする
- Add IPでConstantを追加する
- xlconstant_0をダブルクリックして以下の設定とする
  - Const Width: 29 (VHDLの実装に合わせる)
  - Const Val: 100000000 (1億)
- 以下のように接続する
  - myIP_clockDiv_0のClk <--> ZYNQのFCLK_CLK0
  - myIP_clockDiv_0のdivide_value[28:0] <--> xlconstant_0のdout[28:0]
- myIP_clockDiv_0のClk_mod上にて右クリック、Make External選択

以上で以下のブロック図ができている。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/835c6fd4-dcfd-7835-7132-16681aecfd44.png)

- Sourcesタブ > design_1.bd上で右クリック、Create HDL Wrappterを選択
  - Let Vivado manager wrapper and auto-update
- Sourcesタブ > Constraints > constrs_1上で右クリック、Add Sources > Add or create constraitsを選択、Nextを押す
  - Create File
  - File name: useClockDiv.xdc
  - Finish
- Run Implementation
 - Save Proejct: Saveを押す
- Open Implementation Design
 - I/O Portsタブを選択し、Scaler ports > Clk_modを展開表示する

Clk_modに実際に点滅させたいLEDを指定する。
http://qiita.com/7of9/items/9f35a6b14f4898690237
によるとD18を選択するとLD2(D18)が点滅するようになるので以下の指定をする。

- Site: D18
- Fixed: チェック
- I/O Std: LVCMOS33

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/e22a139e-2af4-8288-e772-5655b9d7ec96.png)

- Ctrl+Sで保存する
  - Save Constraintsウィンドウにて Select an existing file: useClockDiv.xdc を選択しOK

- Generate Bit Stream

- File > Export > Export Hardware...
  - Include bitstreamチェックしてOKクリック
- File > Launch SDK
  - OKクリック

### on XSDK

XSDK上では特にやることはない。
上記の実装でLD2(D18)が点滅するようになっているので、Hello Wolrdのアプリを実装して実行をすればいい。

- File > New > Application Project
  - Project name: ledBlink
  - Nextクリック
  - Hellow Worldを選択してFinish

- メニュー Xilinx Tools > Program FPGA > Programを押す
- Project ExplorerのledBlink > Binaries > ledBlink .elf上で右クリックして、Run As > 1. Launch on Hardware (System Debugger)で実行する

以上でZYBOのLD2(D18)が1HZで点灯するようになる。


![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/6ef2cc95-4dd0-c7b9-5dd8-423328817651.png)


## 補足

1Hzでの点滅を確認できた。
Const Val: 100000000 (1億)をConst Val: 300000000 (3億)にすると、0.33HzでゆっくりしたLEDの点灯を確認できた。

一応動いているようだ。

Clock Dividerを使えば、高速のH/L切替現象をAnalog Discovery(30MHz上限)で測定できるようになると期待している。