発であれば gdb などのデバッガも使う。print デバッグは大量のデータが行きかう場合や順序性だったり、そもそも問題の原因がピンポイントでわからない、といったときは情報出力してそこから推察する時に便利に使える手法だ。
高位合成でも使えないか?Polyphony でトライしてみよう。
クロックレベルが必要な実際の UART の送信 Transmitter はVerilog で実現し、Polyphony では UART モジュールを作る。イメージとしては次のような図になる。
Polyphony の UART モジュールは tx-que でデータを受けて、実際の UART の処理は Verilog-HDL で書いた UART Transmitter モジュールに依頼する。
uart.py
import polyphony
from polyphony import is_worker_running
from polyphony.io import Port, Queue
from polyphony.typing import bit, uint8
from polyphony.timing import clksleep, clkfence, wait_value
@polyphony.module
class Transmitter:
def __init__(self):
self.tx_start = Port(bit, 'out', 0)
self.tx_data = Port(uint8, 'out', 0)
self.tx_busy = Port(bit, 'in')
self.tx_q = Queue(uint8, 'any')
self.append_worker(self.tx_worker)
#self.append_worker(self.func)
def tx_worker(self):
while is_worker_running():
data = self.tx_q.rd()
#for i in range(len(data)):
wait_value(0, self.tx_busy)
self.tx_start.wr(1)
self.tx_data.wr(data)
print(data)
clkfence()
self.tx_start.wr(0)
# def write(self, msg):
# for d in msg:
# self.tx_q.wr(d)
def write_hex16(self, v):
d = (v >> 8) & 0xff
self.tx_q.wr(d)
d = (v) & 0xff
self.tx_q.wr(d)
# def func(self):
# while is_worker_running():
# data = (0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21)
# self.write(data)
@polyphony.testbench
def test(tx):
tx.tx_busy.wr(1)
tx.tx_busy.wr(0)
wait_value(1, tx.tx_start)
print(tx.tx_data.rd())
wait_value(1, tx.tx_start)
print(tx.tx_data.rd())
wait_value(1, tx.tx_start)
print(tx.tx_data.rd())
wait_value(1, tx.tx_start)
print(tx.tx_data.rd())
wait_value(1, tx.tx_start)
print(tx.tx_data.rd())
if __name__ == '__main__':
tx = Transmitter()
test(tx)
UART のソースは fpga4fun.com から拝借する。
これでなんとなく UART のデバッグが出来るようになった気がする。このソースでは、実際のところ printf 的なところはまだむずかしい。write_hex16 で16進数字を表示するにとどまる。