ICE40HX8K AD9225 ADC with Nmigen
This is a first stab at getting the AD9225 ADC working with the ICE48HX8K. I don’t really know my way around python or Nmigen, so these notes most likely do not represent the right way of doing things. But it somewhat works…
The AD9225 is a part pulled from an old CCD camera. It’s a 25MSPS 12bit ADC. I’m not driving it this fast in this test, nor is the UART currently dumping all 12bits. Most likely the Resource can be better refactored so that the clock and data pins are part of the same Resource… Anyway, here’s the code:
#!/usr/bin/python3
from nmigen import *
from uart import *
from nmigen_boards.ice40_hx8k_b_evn import *
from nmigen.build import *
from pll import PLL
class Top(Elaboratable):
def elaborate(self, platform):
# B1 is clock
adcclk = [ Resource("ad9225clk", 0, Pins("B1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")) ]
adc = [ Resource("ad9225", 0, Pins("B2 C1 C2 D1 D2 E2 F1 F2 G1 G2 H1", dir="i"), Attrs(IO_STANDARD="SB_LVCMOS")) ]
platform.add_resources(adc)
platform.add_resources(adcclk)
# PLL Stuff
# If you don't specify dir='-', you will experience a world
# of debugging pain.
clk_pin = platform.request(platform.default_clk, dir='-')
m = Module()
pll = PLL(freq_in_mhz=12, freq_out_mhz=96)
m.domains += pll.domain # override the default 'sync' domain
timer = Signal(28)
#Connect TX to B12
led0 = platform.request('led', 0)
muart = platform.request('uart')
data = platform.request('ad9225',0)
dataclk = platform.request('ad9225clk',0)
dataA = Signal(8)
rdy = Signal(1)
with m.If(timer[25]):
m.d.sync += [
rdy.eq(1),
timer.eq(0)
]
with m.Else():
m.d.sync += [
timer.eq(timer + 1)
]
with m.If(rdy == 1):
m.d.sync += [
rdy.eq(0)
]
m.d.sync += [
dataA.eq(data.i[0:8] + 0x60),
]
m.d.comb += [
pll.clk_pin.eq(clk_pin),
dataclk.eq(timer[20])
]
# UART
uart = UART(divisor=10000)
uart.tx_o = muart.tx
m.d.comb += [
uart.tx_data.eq(dataA),
uart.tx_rdy.eq(rdy)
]
m.submodules += [pll, uart]
return m
if __name__ == '__main__':
platform = ICE40HX8KBEVNPlatform()
platform.build(Top(), do_program=True)
The above code should output ADC values via the FT2232. This is what I get when driving the ADC with a 0.1Hz 3v square wave. The AD9225 is running at 3.3v (analog and digital):
jbnb_______________bmjalaocbkbka______________ck
klbmbmamoc_______________clakbobnbm
ldh______________nbmblajboblald______________akbk
mobmn_ka_______________cncmal]h_lelk
______________kbm_