Skip to content

Commit

Permalink
Merge pull request #2 from NateMeyer/beta-test
Browse files Browse the repository at this point in the history
Beta Development
  • Loading branch information
Johnsel authored Aug 16, 2024
2 parents dabca9a + e24e080 commit 0fd27d5
Show file tree
Hide file tree
Showing 9 changed files with 338 additions and 266 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
build/
__pycache__/
__pycache__/
software/
*.vcd
*.jou
*.log
*.csv
*.cfg
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ BSD 2-Clause License
Copyright (c) 2024, Enjoy-Digital
Copyright (c) 2024, EEVengers
Copyright (c) 2024, John Simons
Copyright (c) 2024, Nate Meyers
Copyright (c) 2024, Nate Meyer

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ $ sudo ./litex_setup.py init install
[> Build and Load the bitstream
--------------------------------
```sh
$ ./thunderscope --driver --build --load
$ ./thunderscope --variant=a200t --driver --build --load
```

| Variant Arg | Target |
| :---------: | :----------------------: |
| `a200t` | Trenz TE0712 200T Module |
| `a100t` | Trenz TE0712 100T Module |
| `a50t` | Custom Rev2 A50T Module |

[> Open LiteX server
--------------------
Over JTAGBone (on local machine):
Expand Down
56 changes: 51 additions & 5 deletions peripherals/had1511_adc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

from migen.genlib.misc import WaitTimer

from litex.gen import *

from litex.soc.interconnect.csr import *
from litex.soc.interconnect import stream

Expand Down Expand Up @@ -54,9 +56,28 @@

had1511_phy_layout = ["fclk_p", "fclk_n", "lclk_p", "lclk_n", "d_p", "d_n"]

# Shuffler -----------------------------------------------------------------------------------------

class ADCByteShuffle(Module):
def __init__(self, num_shuffle, byte_swap = []):
self.sink = sink = stream.Endpoint([("data", len(byte_swap[0])*8)])
self.source = source = stream.Endpoint([("data", len(byte_swap[0])*8)])

self.shuffle = Signal(num_shuffle)

self.comb += sink.connect(source)

for i in range(len(byte_swap[0])):
cases = {}
for idx, swap in enumerate(byte_swap):
cases[idx] = self.source.data[i*8:(i+1)*8].eq(self.sink.data[swap[i]*8:(swap[i]+1)*8])

self.comb += Case(self.shuffle, cases)


# HAD1511 ADC --------------------------------------------------------------------------------------

class HAD1511ADC(Module, AutoCSR):
class HAD1511ADC(LiteXModule):
def __init__(self, pads, sys_clk_freq, lanes_polarity=[0]*8, clock_domain="sys"):
# Parameters.
if pads is not None:
Expand Down Expand Up @@ -86,6 +107,15 @@ def __init__(self, pads, sys_clk_freq, lanes_polarity=[0]*8, clock_domain="sys")
])
self._bitslip_count = CSRStatus(32, description="ADC bitslip count (with rollover).")
self._sample_count = CSRStatus(32, description="ADC samples count since last stat_rst.")
self._data_channels = CSRStorage(fields=[
CSRField("shuffle", offset=0, size=2, reset=0, description="Number of enabled channels to control shuffling of samples",
values=[
(0, "Passthrough"),
(1, "2-Channel Shuffling"),
(2, "4-Channel Shuffling")
]),
CSRField("run_length", offset=2, size=6, reset=1, description="Control Run-Length of samples for each channel ordered next to each other")
])

# # #

Expand Down Expand Up @@ -244,17 +274,32 @@ def __init__(self, pads, sys_clk_freq, lanes_polarity=[0]*8, clock_domain="sys")
# ----------------------

self.submodules.cdc = stream.ClockDomainCrossing(
layout = [("data", nchannels*8)],
cd_from = "adc_frame" if pads is not None else clock_domain,
cd_to = clock_domain
layout = [("data", nchannels*8)],
cd_from = "adc_frame" if pads is not None else clock_domain,
cd_to = clock_domain,
buffered = True,
depth = 256
)
self.comb += self.adc_source.connect(self.cdc.sink)

# Shuffler.
# ---------

# Data from the HMCAD1520 comes in the order [1 1 2 2 3 3 4 4] for 4-channel operation
# and [1 1 1 1 2 2 2 2] for 2-channel operation. Shuffle the data so the output data
# stream is [1 2 3 4 1 2 3 4] and [1 2 1 2 1 2 1 2] respectively.

self.adc_shuffler = ADCByteShuffle(3, byte_swap=[[0, 1, 2, 3, 4, 5, 6, 7],
[0, 4, 1, 5, 2, 6, 3, 7],
[0, 2, 4, 6, 1, 3, 5, 7]])
self.comb += self.adc_shuffler.shuffle.eq(self._data_channels.fields.shuffle)
self.comb += self.cdc.source.connect(self.adc_shuffler.sink)

# DownSampling.
# -------------

self.submodules.downsampling = DownSampling(ratio=self._downsampling.storage)
self.comb += self.cdc.source.connect(self.downsampling.sink)
self.comb += self.adc_shuffler.source.connect(self.downsampling.sink)
self.comb += self.downsampling.source.connect(source)
self.comb += self.downsampling.source.ready.eq(1) # No backpressure allowed.

Expand Down Expand Up @@ -335,6 +380,7 @@ def reset(self):
self.control.write(HAD1511_CORE_CONTROL_FRAME_RST)

def set_reg(self, reg, value):
print(f"hmcad 0x{reg:02X} 0x{value:04X}")
self.spi.write(0, [reg, (value >> 8) & 0xff, value & 0xff])

def set_gain(self, gain):
Expand Down
31 changes: 25 additions & 6 deletions peripherals/zl30260.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
# D E F I N I T I O N S #
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

zl30260_I2C_ADDR = 0x74
zl30260_I2C_WRITE_COMMAND = 0x02
zl30260_I2C_CONF = {
ZL30260_I2C_ADDR = 0x74
ZL30260_I2C_WRITE_COMMAND = 0x02
ZL30260_I2C_READ_COMMAND = 0x03
ZL30260_I2C_CONF = {
# From configuration tool (Reg : Value).
0x0423 : 0x08,
0x0003 : 0x01,
Expand Down Expand Up @@ -66,26 +67,44 @@
# S O F T W A R E #
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #

class zl30260Driver:
class ZL30260Driver:
def __init__(self, bus, name, addr):
self.i2c = I2CDriver(bus=bus, name=name)
self.addr = addr

def init(self, config, debug=False):
for reg, value in config.items():
if debug:
print(f"0x{reg:02x}", end="")
print(f"0x{ZL30260_I2C_WRITE_COMMAND:02x} 0x{reg:04x} : 0x{value:02x}", end="")
ack = 0
while (not ack):
if debug:
print(".", end="")
sys.stdout.flush()
self.i2c.start_cond()
ack = self.i2c.write(I2C_W_ADDR(self.addr))
ack = self.i2c.write(zl30260_I2C_WRITE_COMMAND)
ack = self.i2c.write(ZL30260_I2C_WRITE_COMMAND)
ack &= self.i2c.write(reg >> 8)
ack &= self.i2c.write(reg & 0xFF)
ack &= self.i2c.write(value)
self.i2c.stop_cond()
if debug:
print("")
# Verify registers
# if debug:
# for reg, value in config.items():
# self.i2c.start_cond()
# ack = self.i2c.write(I2C_W_ADDR(self.addr))
# ack = self.i2c.write(ZL30260_I2C_READ_COMMAND)
# ack &= self.i2c.write(reg >> 8)
# ack &= self.i2c.write(reg & 0xFF)
# self.i2c.stop_cond()
# self.i2c.start_cond()
# ack = self.i2c.write(I2C_R_ADDR(self.addr))
# readBack = self.i2c.read(0)
# self.i2c.stop_cond()
# if(readBack == value):
# print(f"Read reg 0x{reg:04X} : 0x{readBack:02X}")
# else:
# print(f"Read reg 0x{reg:04X} : 0x{readBack:02X} (expected 0x{value:02X})")

121 changes: 0 additions & 121 deletions test/csr.csv

This file was deleted.

29 changes: 20 additions & 9 deletions test/test_adc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from peripherals.trigger import *
from peripherals.had1511_adc import *
from peripherals.zl30250 import *
from peripherals.zl30260 import *

from test_i2c import *

Expand Down Expand Up @@ -63,14 +64,24 @@ def afe_configure(host, port, channel, coupling, attenuation):
print("---------------------------------------")

# LDO.
def configure_ldo(enable):
def configure_fe_ldo(enable):
control_value = bus.regs.frontend_control.read()
control_value &= ~( 1 * AFE_CONTROL_LDO_EN)
control_value |= (enable * AFE_CONTROL_LDO_EN)
bus.regs.frontend_control.write(control_value)

print("- Enabling LDO.")
configure_ldo(1)
print("- Enabling FE LDO.")
configure_fe_ldo(1)

# LDO.
def configure_adc_ldo(enable):
control_value = bus.regs.adc_control.read()
control_value &= ~( 1 * ADC_CONTROL_LDO_EN)
control_value |= (enable * ADC_CONTROL_LDO_EN)
bus.regs.adc_control.write(control_value)

print("- Enabling ADC LDO.")
configure_adc_ldo(1)

# Coupling.
def configure_coupling(channel, coupling):
Expand Down Expand Up @@ -121,7 +132,7 @@ def pga_configure(host, port, channel, preamp_db, atten_db, bw_mhz, offset):

# LMH6518.
print("- Configuring LMH6518 (SPI)...")
pga = LMH6518Driver(bus=bus, name="frontend_spi")
pga = LMH6518Driver(bus=bus, name="main_spi")
pga.set(channel, preamp_db, atten_db, bw_mhz)

# MCP4728.
Expand Down Expand Up @@ -160,12 +171,12 @@ def configure_pll(enable):
control_value |= (enable * ADC_CONTROL_PLL_EN)
bus.regs.adc_control.write(control_value)

print("- Enabling ZL30250 PLL.")
print("- Enabling ZL30260 PLL.")
configure_pll(1)

print("- Configuring ZL30250 PLL (I2C)...")
zl30250 = ZL30250Driver(bus=bus, name="i2c", addr=ZL30250_I2C_ADDR)
zl30250.init(config=ZL30250_I2C_CONF, debug=True)
print("- Configuring ZL30260 PLL (I2C)...")
zl30250 = ZL30260Driver(bus=bus, name="i2c", addr=ZL30260_I2C_ADDR)
zl30250.init(config=ZL30260_I2C_CONF, debug=True)

# PWR_DOWN.
def configure_pwr_down(enable):
Expand All @@ -190,7 +201,7 @@ def configure_rst(enable):

# HAD1511.
print("- Configuring HAD1511 (SPI)...")
spi = SPIDriver(bus=bus, name="frontend_spi")
spi = SPIDriver(bus=bus, name="main_spi")
adc = HAD1511ADCDriver(bus, spi, n=0)
adc.reset()
adc.downsampling.write(downsampling)
Expand Down
Loading

0 comments on commit 0fd27d5

Please sign in to comment.