LoginSignup
1
1

More than 5 years have passed since last update.

Python で FPGA/UART を使う(Zybo 編)

Posted at

UART を使う

Linux の UART ドライバと通信しようとおもいます。そのためにはどういうわけか u-boot から作り直さないといけないらしい。

先にデザイン

ざっくりとしたデザインを先に示します。async_trasnmitter というモジュールを使っています。これは verilog で書かれたもので python ではない。fpga4fun.com から拝借しています。

async.v

image.png

async_transmitter はダブルクリックで paramter を変更できます。基準のクロックが 125MHz なので初期設定の 50MHz から変更しておきます。

image.png

合成して実験

vio から 0x31 を送信する。あ、Linux が立ち上がったが気にしない。design_1_i/vio_0_probe_out0 に 1 を書いた瞬間に動き出します。

image.png

結果は 1 だらけになってとまりません。コントロールしてないから。
image.png

Zynq 側の UART をつかうと

参考までに書くと Zynq 側の UART0 を有効にする dtb を書いてみるとうまく Linux が動きません。当たり前ですが、u-boot で行われる初期化と Linux の初期化が不一致だと最悪、立ち上がらないようです。

なので上のデザインは PMOD から UART をだして USB-UART 経由で PC(Windows) と通信してます。

受信側追加

1の無限送信じゃ面白くないので echo バックさせる回路にします。

image.png

受信側も 125MHz にするパラメタ設定をします。そうしないと文字化けしますよ(経験者は語る)。

image.png

ピンの設定もつけておきましょう。

zybo.xdc
## PL System Clock
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 8.000 -name sys_clk_pin -waveform {0.000 4.000} -add [get_ports clk]

## LED
set_property -dict {PACKAGE_PIN M14 IOSTANDARD LVCMOS33} [get_ports led0]

## Buttons
set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports btn0]

set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports TxD_0]
set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports RxD_0]

うまく動きました。 Hello Hello と書いてあるのがエコーバックされた文字。そのまえの 1の羅列がひとつ前の処理。そして部分的に文字化けしているのが失敗した処理。

image.png

Polyphony を使う

ここまでは Polyphony つかってません。はい。使ってませんでした。フィルターとして大文字を小文字に小文字を大文字にするモジュールを作ります。

image.png

letter_x.py
import polyphony
from polyphony import is_worker_running
from polyphony.io import Port, Queue
from polyphony.typing import bit, bit8
from polyphony.timing import clksleep, clkfence, wait_value


@polyphony.module
class letter_x:
    def __init__(self):
        self.tx_start = Port(bit, 'out', 0)
        self.tx_data = Port(bit8, 'out', 0)
        self.tx_busy = Port(bit, 'in')

        self.rx_ready = Port(bit, 'in')
        self.rx_data = Port(bit8, 'in')

        self.append_worker(self.main_worker)

    def main_worker(self):
        while is_worker_running():
            wait_value(1, self.rx_ready)
            data = self.rx_data.rd()

            if ( data > 0x40 ) &  ( data < 0x60 ) :
                data += 0x20
            elif ( data > 0x60 ) &  ( data < 0x80 ) :
                data -= 0x20

            wait_value(0, self.tx_busy)
            self.tx_data.wr(data)
            self.tx_start.wr(1)

            clkfence()
            self.tx_start.wr(0)
            wait_value(0, self.tx_busy)

            print(data)

@polyphony.testbench
def test(obj):
    data_list = (0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21)
    obj.tx_busy.wr(0)
    obj.rx_ready.wr(0)

    for iter in data_list:
        obj.rx_data.wr(iter)
        obj.rx_ready.wr(1)
        clkfence()

        obj.rx_ready.wr(0)
        wait_value(1, obj.tx_start)
        data = obj.tx_data.rd()
        print(data)

if __name__ == '__main__':
    obj = letter_x()
    test(obj)

コンパイルして Vivado に埋め込み合成実行してみます(駆け足ですいません)。

image.png

分かりずらいですが Hello Good-Bye がエコーバックされて hELLO gOOD-bYE になりました。

ついでだから関数化する

worker だの clkfence だのが出てきてわかりづらいので、関数化/ライブラリ化してしまいます。

filter.py
 cat filter.py
def filter_func(data):
    if ( data > 0x40 ) &  ( data < 0x60 ) :
        data += 0x20
    elif ( data > 0x60 ) &  ( data < 0x80 ) :
        data -= 0x20

    return data

使う側では import したうえで filter_func を呼べばいいだけです。これでややこしい部分は外に出せました。

使う側
from filter import filter_func
<>
    def main_worker(self):
        while is_worker_running():
            wait_value(1, self.rx_ready)
            data = self.rx_data.rd()

            data = filter_func(data)

            wait_value(0, self.tx_busy)
            self.tx_data.wr(data)
            self.tx_start.wr(1)

            clkfence()
            self.tx_start.wr(0)
            wait_value(0, self.tx_busy)

            print(data)



1
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
1
1