このシリーズについて
このシリーズは,僕がPYNQ-Z2を使いこなせるようになるまでの道程を記録するものです.
知らないことや分からないことは「知らない」「分からない」と正直に書いていきますのでご教授下さると幸いです.
ハードとソフト
- ハード
- PYNQ-Z2
- 7セグメントLED(型番は不明,7個のLEDにそれぞれhighを送ることで消灯,lowを送ることで点灯するタイプ)
- ソフト
- Vivado 2022.2
RTLモジュール
seven_seg_driver
数字を受け取り,7セグに出力するものです.
なお,7セグはダイナミック点灯ではなく普通の点灯とし,Pmod二つで二桁表示することにします.
モジュールとしては8ビットの信号を受け取り,上位4ビットと下位4ビットをそれぞれ一桁の7セグに十六進数で表示します.
そのため,非常にややこしいですが8ビットの数字を二桁に分け,一桁につき8ビットずつ合計16ビットのレジスタで表示する形になります.
number_2seg
関数は,4ビットの数字から7セグの信号を作っています.反転しているのは,7セグが負論理だからです.
module seven_seg_driver(
input [7:0] number,
output [7:0] left_number,
output [7:0] right_number
);
assign left_number = number2seg(number[7:4]);
assign right_number = number2seg(number[3:0]);
function [7:0] number2seg(input [3:0] number);
case (number)
4'h0: number2seg = ~8'b11111100;
4'h1: number2seg = ~8'b01100000;
4'h2: number2seg = ~8'b11011010;
4'h3: number2seg = ~8'b11110010;
4'h4: number2seg = ~8'b01100110;
4'h5: number2seg = ~8'b10110110;
4'h6: number2seg = ~8'b10111110;
4'h7: number2seg = ~8'b11100000;
4'h8: number2seg = ~8'b11111110;
4'h9: number2seg = ~8'b11110110;
4'ha: number2seg = ~8'b11101110;
4'hb: number2seg = ~8'b00111110;
4'hc: number2seg = ~8'b10011100;
4'hd: number2seg = ~8'b01111010;
4'he: number2seg = ~8'b10011110;
4'hf: number2seg = ~8'b10001110;
endcase
endfunction
endmodule
number_generator
7セグに表示するための数字を作成するモジュールです.
入出力にレジスタが使えることを知りませんでした.
module number_generator(
input clk,
input resetn,
output reg [7:0] number
);
parameter [31:0] CYCLE = 32'd50_000_000;
reg [31:0] count = 32'b1;
always @(posedge clk) begin
if (!resetn) begin
count <= 32'b1;
number <= 8'b0;
end else begin
if (count == CYCLE) begin
count <= 32'b1;
number <= number + 8'b1;
end else begin
count <= count + 32'b1;
end
end
end
endmodule
ブロックデザイン
ブロックデザインは以下の手順で作成しました.
arty-s7の時はボードファイルがあると便利でしたので,PYNQ-Z2でも同様に公式サイトにてボードファイルをダウンロードし,所定の位置に置いたのですが,結局ここでは使用しませんでした.
1.Create Block Design
で空のブロックデザインを作る.
2.+
ボタンまたはctrl+I
を押し,ZYNQ7 Processing System
を追加する(「zynq」などで検索するとトップに出てくる)
3.Run Block Automation
をクリックし,以下の様にレ点が付いていることを確認しOKを押す.
4.先ほど作成したseven_seg_driver
とnumber_generator
を,ドラッグアンドドロップでブロックデザインに追加する.
5.Run Connection Automation
を押し,Clock Source
を確認しOKを押す.
7.以下のように配線する(FCLK_CLK0
とM_AXI_GP0_ACLK
をつなぐのを忘れないように).
8.Create HDL Wrapper
し,ラッパーファイルをトップに設定する
制約ファイル
Pmodの部分だけですのでこれだけです.
##PmodA
set_property -dict { PACKAGE_PIN Y18 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L17P_T2_34 Sch=ja_p[1]
set_property -dict { PACKAGE_PIN Y19 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L17N_T2_34 Sch=ja_n[1]
set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L7P_T1_34 Sch=ja_p[2]
set_property -dict { PACKAGE_PIN Y17 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L7N_T1_34 Sch=ja_n[2]
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L12P_T1_MRCC_34 Sch=ja_p[3]
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L12N_T1_MRCC_34 Sch=ja_n[3]
set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22P_T3_34 Sch=ja_p[4]
set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22N_T3_34 Sch=ja_n[4]
##PmodB
set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L8P_T1_34 Sch=jb_p[1]
set_property -dict { PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L8N_T1_34 Sch=jb_n[1]
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L1P_T0_34 Sch=jb_p[2]
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L1N_T0_34 Sch=jb_n[2]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L18P_T2_34 Sch=jb_p[3]
set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L18N_T2_34 Sch=jb_n[3]
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L4P_T0_34 Sch=jb_p[4]
set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L4N_T0_34 Sch=jb_n[4]
結果
無事,点灯しました!
・・・のですが,しばらくするとCPUが起動してしまい,7セグは光らなくなってしまいました.
CPUを使わずやってみる
上の原因として,ブロックデザインにzynqを含めたことが関係あるのでは? と考察し,PYNQ-Z2に搭載されている125MHzのクロックを利用してやり直してみました.
ブロックデザインはこんな感じ.
すると,先ほどとクロック周波数が異なるので値の更新速度こそ違いますが,途中でCPUが起動したりすることなくオーバーフローするまでカウントが進みました.
Arty S7-50しか触ってこなかったのでPYNQ-Z2のCPUの仕様がよくわからないのですが,必要ないときはブロックデザインに含めない方がいいようです.
CPUについてはまだまだ知らないことだらけな上,中身についてまで解説してくれているサイトはなかなかないので実験しながら理解していくしかなさそうです.
次回は
PS-PL間のデータ共有についてまとめます.