0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PYNQで7セグ(PYNQシリーズ)

Posted at

このシリーズについて

このシリーズは,僕が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で空のブロックデザインを作る.

image.png

2.+ボタンまたはctrl+Iを押し,ZYNQ7 Processing Systemを追加する(「zynq」などで検索するとトップに出てくる)

image.png

3.Run Block Automationをクリックし,以下の様にレ点が付いていることを確認しOKを押す.

image.png

4.先ほど作成したseven_seg_drivernumber_generatorを,ドラッグアンドドロップでブロックデザインに追加する.

image.png

5.Run Connection Automationを押し,Clock Sourceを確認しOKを押す.

image.png

7.以下のように配線する(FCLK_CLK0M_AXI_GP0_ACLKをつなぐのを忘れないように).

image.png

8.Create HDL Wrapperし,ラッパーファイルをトップに設定する

制約ファイル

Pmodの部分だけですのでこれだけです.

top.xdc
##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のクロックを利用してやり直してみました.

ブロックデザインはこんな感じ.

image.png

すると,先ほどとクロック周波数が異なるので値の更新速度こそ違いますが,途中でCPUが起動したりすることなくオーバーフローするまでカウントが進みました.

Arty S7-50しか触ってこなかったのでPYNQ-Z2のCPUの仕様がよくわからないのですが,必要ないときはブロックデザインに含めない方がいいようです.

CPUについてはまだまだ知らないことだらけな上,中身についてまで解説してくれているサイトはなかなかないので実験しながら理解していくしかなさそうです.

次回は

PS-PL間のデータ共有についてまとめます.

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?