新千葉 ガーベージ・コレクション

FPGA マガジンやインターフェースで書けなかったこと等をちょぼちょぼ書いてます。@ryos36

Polyphony で SPI

Vivado HLS でいろいろ試していたのですが、結局、この手のは Python で書いて、Polyphony で Verilog に落とすことにしました。

polyphony のバージョンは 0.3.0 を使用。
GitHub - ktok07b6/polyphony: Polyphony is Python based High-Level Synthesis compiler. から 0.3.0 の branch を使用してください。最新だとエラーになる模様。

import polyphony
from polyphony.io import Bit, Uint
from polyphony.timing import clksleep, clkfence, wait_rising, wait_falling
import pdb


CONVST_PULSE_CYCLE = 10
CONVERSION_CYCLE = 40


@polyphony.module
class SPIController:
    def __init__(self):
        self.sclk = Bit()
        self.sdo  = Bit()
        self.sdi  = Bit()
        self.convst_n = Bit(init=1)
        self.cs_n = Bit(init=1)
        self.dout = Uint(width=12)
        self.chout = Uint(width=3)
        self.din = Uint(width=16)
        self.data_ready = Bit()
        self.append_worker(self.main)

    def main(self):
        while polyphony.is_worker_running():
            self.convst_n.wr(1)
            self.cs_n.wr(1)
            self.data_ready.wr(0)
            clkfence()

            self.convst_n.wr(0)
            clksleep(CONVST_PULSE_CYCLE)

            self.convst_n.wr(1)
            clksleep(CONVERSION_CYCLE)

            # starting ADC I/O
            self.cs_n.wr(0)
            sdo_tmp = 0
            clksleep(1)

            for i in range(16):
                self.sclk.wr(0)
                sdi_tmp = 1 if (self.din() & (1 << (15-i))) else 0
                self.sdi.wr(sdi_tmp)
                clksleep(1)

                self.sclk.wr(1)
                sdo_tmp = sdo_tmp<<1 | self.sdo.rd()

            self.sclk.wr(0)
            self.dout.wr(sdo_tmp & 0x0fff)
            self.chout.wr((sdo_tmp & 0x7000)>>12)
            self.cs_n.wr(1)
            clkfence()
            self.data_ready.wr(1)

これを polyphony で光合成。じゃなくて高位合成。

> ../bin/polyphony spi.py
> ls
polyphony_out.v  polyphony_out_SPIController_spic.v  spi.py

Vivado に入れてみる。

f:id:ryos36:20170228215651p:plain

なんとなくできた。