Artyで遊びました

#概要

* Vivado 使用
* [ARTY](https://japan.xilinx.com/products/boards-and-kits/arty.html#documentation) 使用

基本的なところを試すことが目的．

制約ファイル参考[サイト](https://www.shuwasystem.co.jp/book/9784798047539.html)
書き方参考[サイト](https://www.acri.c.titech.ac.jp/wordpress/archives/3449)


#ボード選択
デフォルトではARTYボードは入っていません．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/edcdd5cc-7b2d-cfcf-afbb-23d8cb590e32.png)
"Install/Update Boards"を選択します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/bf82b749-8bad-c901-69fc-3945264538f7.png)
ARTYを検索すれば完了です．

#書き込み手順
「Hardware manager」の「Program Device」でbitファイルを選択し，「Program」で書き込めます．
生成したbitファイルは，プロジェクトの「runs」->「impl_1」に入ってます．

#LED　ON
まず，LEDをONにするコードです．

```LED.v
`timescale 1ns / 1ps

module LED(
    output LED
    );
    
    assign LED = 1;
    
endmodule

```

```LED.xdc
## Arty constraints file
## chapter: 2
## project: blink

#Clock signal
set_property PACKAGE_PIN E3 [get_ports {CLK}]
set_property IOSTANDARD LVCMOS33 [get_ports {CLK}]
create_clock -add -name sys_clk_pin -period 10.00 \
    -waveform {0 5} [get_ports {CLK}]

#Reset
set_property PACKAGE_PIN B8 [get_ports {RST}]
set_property IOSTANDARD LVCMOS33 [get_ports {RST}]

#LEDs
set_property PACKAGE_PIN H5  [get_ports {LED}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED}]

##Buttons
set_property PACKAGE_PIN D9 [get_ports {switch1}]
set_property IOSTANDARD LVCMOS33 [get_ports {switch1}]

```

#switchを使用する
次にスイッチをONにするとLEDをONにします．
拘束ファイルは変えずに行います．

```switch.v
`timescale 1ns / 1ps

module LED(
    output LED,
    input switch1
    );
    
    assign LED = switch1;
    
endmodule
```

論理回路図を見る際はRTL ANALYSIS で確認できます．
![RTL１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/cf2d1d1b-00a8-a7f7-9c74-d88031dd4ecd.png)

今回は単純に直結なので一直線になります．


#マルチカラーLED
ここから，拘束ファイルは自作しました．
[回路図](https://reference.digilentinc.com/_media/arty:arty_sch.pdf)から持ってきただけとも言えますが
error がわかりにくいため，だいぶ苦戦しました．

```multiLED.v
`timescale 1ns / 1ps

module multiLED(
    input [3:0] SW,
    output [3:0] LED,
    output [2:0] LED0,
    output [2:0] LED1,
    output [2:0] LED2,
    output [2:0] LED3
    );
    
    assign LED = SW;
    assign LED0 = SW[2:0];
    assign LED1 = SW[2:0];
    assign LED2 = SW[2:0];
    assign LED3 = SW[2:0];
    
endmodule
```

```multiLED.xdc
## Arty constraints file
## chapter: 2
## project: blink

#Clock signal
set_property PACKAGE_PIN E3 [get_ports {CLK}]
set_property IOSTANDARD LVCMOS33 [get_ports {CLK}]
create_clock -add -name sys_clk_pin -period 10.00 \
    -waveform {0 5} [get_ports {CLK}]

#Reset
set_property PACKAGE_PIN B8 [get_ports {RST}]
set_property IOSTANDARD LVCMOS33 [get_ports {RST}]

#LEDs
set_property PACKAGE_PIN H5  [get_ports {LED[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]

set_property PACKAGE_PIN J5  [get_ports {LED[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]

set_property PACKAGE_PIN T9  [get_ports {LED[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}]

set_property PACKAGE_PIN T10 [get_ports {LED[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}]

#multiColor LEDs  RGB
set_property PACKAGE_PIN G6  [get_ports {LED0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED0[0]}]

set_property PACKAGE_PIN F6  [get_ports {LED0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED0[1]}]

set_property PACKAGE_PIN E1  [get_ports {LED0[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED0[2]}]


set_property PACKAGE_PIN G3  [get_ports {LED1[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED1[0]}]

set_property PACKAGE_PIN J4  [get_ports {LED1[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED1[1]}]

set_property PACKAGE_PIN G4  [get_ports {LED1[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED1[2]}]


set_property PACKAGE_PIN J3  [get_ports {LED2[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED2[0]}]

set_property PACKAGE_PIN J2  [get_ports {LED2[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED2[1]}]

set_property PACKAGE_PIN H4  [get_ports {LED2[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED2[2]}]


set_property PACKAGE_PIN K1  [get_ports {LED3[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED3[0]}]

set_property PACKAGE_PIN H6  [get_ports {LED3[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED3[1]}]

set_property PACKAGE_PIN K2  [get_ports {LED3[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED3[2]}]
##Switches
set_property PACKAGE_PIN A8  [get_ports {SW[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SW[0]}]

set_property PACKAGE_PIN C11 [get_ports {SW[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SW[1]}]

set_property PACKAGE_PIN C10 [get_ports {SW[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SW[2]}]

set_property PACKAGE_PIN A10 [get_ports {SW[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {SW[3]}]
```
![result1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/32546cc7-65ee-cfe0-dfe7-a12a4dfc55d3.png)
めっちゃ明るいです．

#順序回路

```
always @ (trigger)
begin 
   statement
end
```
とすると，トリガーが入るとstatementが実行されます．


```
module always2020(
    output LED,
    input switch1
    );
    
    reg F;
    wire LED;
    
    always @ (switch1)
    begin
        if(F == 0)
            F <=1;
        else
            F <= 0;
    end
    
    assign LED = F;
    
endmodule
```

これだと

```
[DRC LUTLP-1] Combinatorial Loop Alert: 1 LUT cells form a combinatorial loop. This can create a race condition. Timing analysis may not be accurate. The preferred resolution is to modify the design to remove combinatorial logic loops. If the loop is known and understood, this DRC can be bypassed by acknowledging the condition and setting the following XDC constraint on any one of the nets in the loop: 'set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets <myHier/myNet>]'. One net in the loop is LED_OBUF. Please evaluate your design. The cells in the loop are: LED_OBUF_inst_i_1.
```
こんなエラーを吐きます．
switch1ごとにレジスタFを反転させて，FをLEDにつないだつもりだったんですが，だめです．
Fの分岐でFを変えるというループ構造がエラーの原因ぽいです．

![RTL2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/e742bb40-35fc-969e-f6a8-b7c548b0454e.png)

生成される回路が，レジスタではなくマルチプレクサなのもおかしいですね．　　　

追記
```
always @ (switch1)
```
のところで，$posedege$をつけ忘れてます．

別のプログラムでは，

```
[DRC NSTD-1] Unspecified I/O Standard: 1 out of 3 logical ports use I/O standard (IOSTANDARD) value 'DEFAULT', instead of a user assigned specific value. This may cause I/O contention or incompatibility with the board power or connectivity affecting performance, signal integrity or in extreme cases cause damage to the device or the components to which it is connected. To correct this violation, specify all I/O standards. This design will fail to generate a bitstream unless all logical ports have a user specified I/O standard value defined. To allow bitstream creation with unspecified I/O standard values (not recommended), use this command: set_property SEVERITY {Warning} [get_drc_checks NSTD-1].  NOTE: When using the Vivado Runs infrastructure (e.g. launch_runs Tcl command), add this command to a .tcl file and add that file as a pre-hook for write_bitstream step for the implementation run. Problem ports: Q_not.
```
このエラーは$Q　not$という出力端子を拘束ファイルに入れていないため発生していました．


#T-FF

```

module TFF(
input T,
output Q
    );
    
reg Q;


always @(posedge T)
begin
    Q <= ~Q;
end
```
これだと

![RTL3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/8fe9ad8e-7eae-b086-ea6a-c8d06ef27758.png)

正しく回路が生成されますが，Implementationで次のエラーを吐きます．

```
[Place 30-574] Poor placement for routing between an IO pin and BUFG. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .xdc file to demote this message to a WARNING. However, the use of this override is highly discouraged. These examples can be used directly in the .xdc file to override this clock rule.
	< set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets T_IBUF] >

	T_IBUF_inst (IBUF.O) is locked to IOB_X0Y137
	 and T_IBUF_BUFG_inst (BUFG.I) is provisionally placed by clockplacer on BUFGCTRL_X0Y31

```

入力Tがクロック入力になっているが，設定されているピンがクロック入力に適していないというエラーではないだろうか．
[こちらに対処法があった](https://marsee101.blog.fc2.com/blog-date-20140820.html)

制約ファイルに

```
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets T_IBUF]
```
を追加したところ，うまくいきました．エラーメッセージにも書いてありましたね．

関係ないですが，回路図の表示で，「Synthesis」のタブの「Schematic」はReloadを押さないと再度Synthesisしても変化しないので注意が必要です．



#シフトレジスタの作成

```Shift_reg.v
module Shift_reg(
output [3:0] LED,
input  SW,
input switch1
    );
    
reg [3:0] D;

always @(posedge switch1)
begin
    D <= (D<<1);
    D[0] <= SW;
end

assign LED = D;   
    
endmodule

```

```shift.xdc
#Reset
set_property PACKAGE_PIN B8 [get_ports {RST}]
set_property IOSTANDARD LVCMOS33 [get_ports {RST}]

#LEDs
set_property PACKAGE_PIN H5  [get_ports {LED[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]

set_property PACKAGE_PIN J5  [get_ports {LED[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]

set_property PACKAGE_PIN T9  [get_ports {LED[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}]

set_property PACKAGE_PIN T10 [get_ports {LED[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}]

##Buttons
set_property PACKAGE_PIN D9 [get_ports {switch1}]
set_property IOSTANDARD LVCMOS33 [get_ports {switch1}]

###Switches
set_property PACKAGE_PIN A8  [get_ports {SW}]
set_property IOSTANDARD LVCMOS33 [get_ports {SW}]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets switch1_IBUF]

```

![RTL4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/6d823c75-5ee0-a44a-75e0-398cf1d8101f.png)

ほぼ一発で成功しました．

#内部クロックと分周回路
回路図のp.5にGCLK100という100MHz発信機出力がE3に入力されています．
よって，E3をクロック入力にして，分周回路を組んでみます．
2^27 = 137M なので，27分周すれば1秒ごとに明滅しますね．

```Clock_test.v
`timescale 1ns / 1ps

module Clock_test(
input clock,
output LED
    );
   
reg [26:0] D; 
always @ (posedge clock)
begin
 D <= D+1;
end

assign LED = D[26];

endmodule

```

```Clock_test.xdc
#Reset
set_property PACKAGE_PIN B8 [get_ports {RST}]
set_property IOSTANDARD LVCMOS33 [get_ports {RST}]

#LEDs
set_property PACKAGE_PIN H5  [get_ports {LED}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED}]



set_property PACKAGE_PIN E3 [get_ports {clock}]
set_property IOSTANDARD LVCMOS33 [get_ports {clock}]

```

特にエラーもなくうまくいって安心しました．

MMCMという機能を使えば任意の周波数を生成できるらしいですが，ちょっと難しいですね．

#複数のIPの接続

```
モジュール名　インスタンス名(.モジュール信号名(接続先信号名))
```
で接続できます．（.A(B)）だと　AをBに接続という感じで　Bのモジュール内で呼び出す感じになります

クロック生成機構をシフトレジスタに接続してみましょう．

```
module Shift_reg(
output [3:0] LED,
input  SW,
input switch1
    );

reg [3:0] D;
wire switch1;

Clock_test Name1(.LED1(switch1));

always @(posedge switch1)
begin
    D <= (D<<1);
    D[0] <= SW;
end

assign LED = D;   
endmodule




module Clock_test(
input clock,
output LED1
    );

reg [26:0] D; 
always @ (posedge clock)
begin
 D <= D+1;
end

assign LED1 = D[26];

endmodule
```
とすると

回路図は成功しています
![RTL5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/31dbb294-72bc-cf5e-116e-e1f5bd50ef12.png)

Imprementationでエラーが発生し

```
[DRC MDRV-1] Multiple Driver Nets: Net Name1/out[0] has multiple drivers: switch1_IBUF_inst/O, and Name1/D_reg[26]/Q.
```
switch1をinputで宣言しているため複数入力になり，エラーと考え

```
input switch1
```
を削除し

```
module Shift_reg(
output [3:0] LED,
input  SW
    );

reg [3:0] D;
wire switch1;

Clock_test Name1(.LED1(switch1));

always @(posedge switch1)
begin
    D <= (D<<1);
    D[0] <= SW;
end

assign LED = D;   
endmodule




module Clock_test(
input clock,
output LED1
    );

reg [26:0] D; 
always @ (posedge clock)
begin
 D <= D+1;
end

assign LED1 = D[26];

endmodule
```
とすると

```
[DRC UCIO-1] Unconstrained Logical Port: 4 out of 4 logical ports have no user assigned specific location constraint (LOC). This may cause I/O contention or incompatibility with the board power or connectivity affecting performance, signal integrity or in extreme cases cause damage to the device or the components to which it is connected. To correct this violation, specify all pin locations. This design will fail to generate a bitstream unless all logical ports have a user specified site LOC constraint defined.  To allow bitstream creation with unspecified pin locations (not recommended), use this command: set_property SEVERITY {Warning} [get_drc_checks UCIO-1].  NOTE: When using the Vivado Runs infrastructure (e.g. launch_runs Tcl command), add this command to a .tcl file and add that file as a pre-hook for write_bitstream step for the implementation run.  Problem ports: LED[3:0].

```
こんなエラーを吐きます．これだと回路図も失敗していました．

![RTL6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/85584177-7ba5-8536-19fa-84f8e585f37a.png)

上のエラーは拘束ファイルにLED[2],[1]を入れ忘れたためでした．
しかし，ここを直すとbitstreamは作れますが，回路図がおかしい通りLEDはずっとLOWのままです．

よく考えると，下位モジュールの"clock"が拘束ファイルしたがってつながると考えていましたが，これも上位モジュールにつなぐ必要があるのかもしれません．その結果，下位モジュールが機能せず，存在が抹消されてLOWになり続ける回路になったのかもしれません．

ー＞成功しました！
![RTL7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/eb559bc3-5043-8e6b-96f9-6b99f350f9f9.png)

いやぁ，エラーの原因までが遠い，遠い，きつい

拘束ファイルの端子名は，すべて上位モジュールの入出力に限定されているようです．

最終結果

```
module Shift_reg(
output [3:0] LED,
input  SW,
input clock
    );

reg [3:0] D;
wire switch1;

Clock_test Name1(.LED1(switch1),.clock(clock));

always @(posedge switch1)
begin
    D <= (D<<1);
    D[0] <= SW;
end

assign LED = D;   
endmodule




module Clock_test(
input clock,
output LED1
    );

reg [26:0] D; 
always @ (posedge clock)
begin
 D <= D+1;
end

assign LED1 = D[26];

endmodule

```

```
#Reset
set_property PACKAGE_PIN B8 [get_ports {RST}]
set_property IOSTANDARD LVCMOS33 [get_ports {RST}]

#LEDs
set_property PACKAGE_PIN H5  [get_ports {LED[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]

set_property PACKAGE_PIN J5  [get_ports {LED[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]

set_property PACKAGE_PIN T9  [get_ports {LED[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}]

set_property PACKAGE_PIN T10 [get_ports {LED[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}]


set_property PACKAGE_PIN E3 [get_ports {clock}]
set_property IOSTANDARD LVCMOS33 [get_ports {clock}]

set_property PACKAGE_PIN A8  [get_ports {SW}]
set_property IOSTANDARD LVCMOS33 [get_ports {SW}]
```

だいぶいろいろ試せて満足できました！
次は，VGAとかALUとか4bitCPUとかできたら面白いですね．


#bitstreamの生成時のエラー

拘束ファイルで設定していない端子をvelilogファイルでoutputかinputで設定していると，エラーになります

```
[DRC NSTD-1] Unspecified I/O Standard: 4 out of 11 logical ports use I/O standard (IOSTANDARD) value 'DEFAULT', instead of a user assigned specific value. This may cause I/O contention or incompatibility with the board power or connectivity affecting performance, signal integrity or in extreme cases cause damage to the device or the components to which it is connected. To correct this violation, specify all I/O standards. 
This design will fail to generate a bitstream unless all logical ports have a user specified I/O standard value defined. To allow bitstream creation with unspecified I/O standard values (not recommended), use this command: set_property SEVERITY {Warning} [get_drc_checks NSTD-1].  NOTE: When using the Vivado Runs infrastructure (e.g. launch_runs Tcl command), add this command to a .tcl file and add that file as a pre-hook for write_bitstream step for the implementation run. Problem ports: OUT_CPU[7], OUT_CPU[6], OUT_CPU[5], and OUT_CPU[4].

```
拘束ファイルに端子が足りてないといっているので，追加してやるか，velilogファイルの方を減らせばOKです．
synthesis,implementationは通るのが気に食わないですが・・・