文章を書くときは vim を使っている。30 年前はマイフェス(MIFES)と ATOK だった。OS は MS-DOS 3.1。未だに、出版社に原稿をあげるときも TeX だったりする。ほぼテキストなので文章は使いまわせる。Lattice のシステムバスにつなぐという話はインタフェースの 2018 年1月号に書いている。その記事を元に構成しなおそう。
ターゲットは Lattice iCE40 だ。iCE40 は内部にシステムバスと呼ばれるものを持っている。非常に簡単なバスでアクセスは比較的簡単だ。雑誌の記事では全ソース載せられてない。200 行を超えるので、ここでも一部としよう。
なお全文は gist にデバッグの生々しいコメントアウトも含めてあげてある。
def read_spi_data16(self):
debug_v:uint3 = 0
debug_v = 4
#self.debug.wr(4)
self.write_data(0x06, 0x18)
self.write_data(0x0A, 0xC0)
self.write_data(0x0D, 0xFF)
while True:
irq_status = self.read_data(0x06)
irq_trdy = (irq_status >> 4) & 1
if irq_trdy == 1 :
self.write_data(0x06, 0x10)
break
self.write_data(0x0D, 0xFF)
#self.debug.wr(5)
debug_v = 1
while True:
irq_status = self.read_data(0x06)
irq_rrdy = (irq_status >> 3) & 1
debug_v = 7 ^ debug_v
# self.debug.wr(debug_v)
if irq_rrdy == 1:
self.write_data(0x06, 0x08)
break
data0 = self.read_data(0x0E) << 8
debug_v = 2
#self.debug.wr(2)
while True:
irq_status = self.read_data(0x06)
irq_rrdy = (irq_status >> 3) & 1
if irq_rrdy == 1:
debug_v = 4 ^ debug_v
#self.debug.wr(debug_v)
self.write_data(0x06, 0x08)
break
data1 = self.read_data(0x0E)
#self.debug.wr(1)
self.write_data(0x0A, 0x80)
return (data0 | data1)
メソッド read_spi_data16 は PmodALS からデータを読み込むプログラムだ。write_data や read_data が実際にシステムバスと通信をしている。
def write_data(self, addr:uint8, data:uint8):
self.rw(1)
self.addr(addr)
self.data_out(data)
clkfence()
self.stb(1)
clkfence()
wait_value(1, self.ack)
clkfence()
self.stb(0)
def read_data(self, addr:uint8):
data:uint8 = 0
self.rw(0)
self.addr(addr)
clkfence()
self.stb(1)
clkfence()
wait_value(1, self.ack)
data = self.data_in.rd()
clkfence()
self.stb(0)
return data
clkfence という特別な関数が順序性の追い越しをしないように制御している。
Polyphony は将来的にもう少しこの辺を便利にしようかとも思っている。ただ、クロックという考え方と、コンパイラがパイプラインを生成するという発想は、著しく相性が悪いことはわかっている。この部分のブレイクスルーがあると次の世代の HLS に行きつくのかもしれない。