from . import Terminal, SubCircuitElement, SPICE_VALUE
from .components.comparator import (
DifferentialOutputClockedComparator,
)
from ..digital_control import DigitalControl as NominalDigitalControl
from ..digital_control.dither_control import DitherControl as NominalDitherControl
from ..analog_system import AnalogSystem
from .components.summer import DifferentialSummer
from .components.reference_source import ReferenceSource
from .components.comparator import DAC_Bridge, D_FLIP_FLOP, ADCBridgeAbsolute
from .components.analog_delay import AnalogDelay
[docs]class DigitalControl(SubCircuitElement):
"""The default digital control circuit.
Parameters
----------
instance_name : str
The instance name of the digital control circuit.
analog_system : AnalogSystem
The analog system to which this digital control circuit belongs.
digital_control : DigitalControl
The digital control circuit to which this digital control circuit belongs.
in_high : float
The high input voltage of the comparator.
in_low : float
The low input voltage of the comparator.
out_high : float
The high output voltage of the comparator.
out_low : float
The low output voltage of the comparator.
dither_offset : int
The offset of the dither control circuit.
"""
def __init__(
self,
instance_name: str,
analog_system: AnalogSystem,
digital_control: NominalDigitalControl,
in_high: float,
in_low: float,
out_high: float,
out_low: float,
dither_offset: int = 0,
):
super().__init__(
instance_name,
"digital_control",
[Terminal("VSS"), Terminal("VDD"), Terminal("CLK"), Terminal("VCM")]
+ [Terminal(f"X{i}_P") for i in range(analog_system.N)]
+ [Terminal(f"X{i}_N") for i in range(analog_system.N)]
+ [Terminal(f"IN{i}_P") for i in range(analog_system.L)]
+ [Terminal(f"IN{i}_N") for i in range(analog_system.L)]
+ [Terminal(f"S{i}_P") for i in range(analog_system.M)]
+ [Terminal(f"S{i}_N") for i in range(analog_system.M)],
)
multi_input_comparator_names = [
f"Xmic_{m}" for m in range(dither_offset, analog_system.M)
]
self.add(
*[
MultiInputComparator(
multi_input_comparator_names[m - dither_offset],
analog_system,
digital_control,
m,
m - dither_offset,
in_high,
in_low,
out_high,
out_low,
)
for m in range(dither_offset, analog_system.M)
]
)
for m_tilde in range(analog_system.M_tilde):
comparator: MultiInputComparator = self.__getattr__(
multi_input_comparator_names[m_tilde]
)
self.connects(
(self["CLK"], comparator["CLK"]),
(self["VSS"], comparator["VSS"]),
(self["VDD"], comparator["VDD"]),
(self["VCM"], comparator["VCM"]),
)
# Connect States
for n in range(analog_system.N):
self.connects(
(self[f"X{n}_P"], comparator[f"X{n}_P"]),
(self[f"X{n}_N"], comparator[f"X{n}_N"]),
)
# Connect inputs
for l in range(analog_system.L):
self.connects(
(self[f"IN{l}_P"], comparator[f"IN{l}_P"]),
(self[f"IN{l}_N"], comparator[f"IN{l}_N"]),
)
# Connect outputs (control signals)
for m in range(analog_system.M):
self.connects(
(self[f"S{m}_P"], comparator[f"S{m}_P"]),
(self[f"S{m}_N"], comparator[f"S{m}_N"]),
)
[docs]class DitherControl(SubCircuitElement):
"""The DitherControl class is a subcircuit element that implements a dither control.
Parameters
----------
instance_name : str
The name of the instance.
analog_system : AnalogSystem
The analog system.
digital_control : NominalDigitalControl
The digital control.
in_high : float
The high input voltage.
in_low : float
The low input voltage.
out_high : float
The high output voltage.
out_low : float
The low output voltage.
clk_delay : float, optional
The clock delay, by default 0.0
t_rise : float, optional
The rise time, by default 1e-15
t_fall : float, optional
The fall time, by default 1e-15
rise_delay : float, optional
The rise delay, by default 1e-15
fall_delay : float, optional
The fall delay, by default 1e-15
set_delay : float, optional
The set delay, by default 1e-15
reset_delay : float, optional
The reset delay, by default 1e-15
input_load : float, optional
The input load, by default 1e-15
"""
out_low: float
out_high: float
out_undef: float
def __init__(
self,
instance_name: str,
analog_system: AnalogSystem,
digital_control: NominalDitherControl,
in_high: float,
in_low: float,
out_high: float,
out_low: float,
clk_delay: float = 0.0,
t_rise: float = 1e-15,
t_fall: float = 1e-15,
rise_delay: float = 1e-15,
fall_delay: float = 1e-15,
set_delay: float = 1e-15,
reset_delay: float = 1e-15,
input_load: float = 1e-15,
):
super().__init__(
instance_name,
"dither_control",
[Terminal("VSS"), Terminal("VDD"), Terminal("CLK"), Terminal("VCM")]
+ [Terminal(f"X{i}_P") for i in range(analog_system.N)]
+ [Terminal(f"X{i}_N") for i in range(analog_system.N)]
+ [Terminal(f"IN{i}_P") for i in range(analog_system.L)]
+ [Terminal(f"IN{i}_N") for i in range(analog_system.L)]
+ [Terminal(f"S{i}_P") for i in range(analog_system.M)]
+ [Terminal(f"S{i}_N") for i in range(analog_system.M)],
)
self._generate_digital_control(
analog_system,
digital_control._deterministic_control,
digital_control.number_of_random_control,
in_high,
in_low,
out_high,
out_low,
)
self._generate_dither_controls(
analog_system,
digital_control,
out_low,
out_high,
(out_high + out_low) / 2.0,
in_low,
in_high,
input_load,
t_rise,
t_fall,
clk_delay,
set_delay,
reset_delay,
rise_delay,
fall_delay,
)
def _generate_dither_controls(
self,
analog_system: AnalogSystem,
digital_control: NominalDitherControl,
out_low: float,
out_high: float,
out_undef: float,
in_low: float,
in_high: float,
input_load: float,
t_rise: float,
t_fall: float,
clk_delay: float,
set_delay: float,
reset_delay: float,
rise_delay: float,
fall_delay: float,
):
source = ReferenceSource(
"Ars",
"r_source",
digital_control.number_of_random_control,
f"dither_sequence_{hash(self)}.txt",
digital_control._pseudo_random_sequence,
time_step=digital_control.clock.T,
)
random_signal_terminals = [
Terminal(f"RS_{m}") for m in range(digital_control.number_of_random_control)
]
flip_flop = [
D_FLIP_FLOP(
f"Adffp_{m}",
"dflip",
clk_delay,
set_delay=set_delay,
reset_delay=reset_delay,
ic=1,
rise_delay=rise_delay,
fall_delay=fall_delay,
)
for m in range(digital_control.number_of_random_control)
]
clk_adc = ADCBridgeAbsolute(
"Aclk_adc",
"adc",
in_low,
in_high,
rise_delay=rise_delay,
fall_delay=fall_delay,
)
dac_p = [
DAC_Bridge(
f"Adac_p_{m}",
"dac",
out_low,
out_high,
out_undef,
input_load,
t_rise,
t_fall,
)
for m in range(digital_control.number_of_random_control)
]
dac_n = [
DAC_Bridge(
f"Adac_n_{m}",
"dac",
out_low,
out_high,
out_undef,
input_load,
t_rise,
t_fall,
)
for m in range(digital_control.number_of_random_control)
]
self.add(source, clk_adc, *flip_flop, *dac_p, *dac_n)
self.connect(self["CLK"], clk_adc["IN"])
for m in range(digital_control.number_of_random_control):
self.connects(
(random_signal_terminals[m], source[m]),
(random_signal_terminals[m], flip_flop[m]["IN"]),
(clk_adc["OUT"], flip_flop[m]["CLK"]),
(flip_flop[m]["F_OUT_P"], dac_p[m]["IN"]),
(flip_flop[m]["F_OUT_N"], dac_n[m]["IN"]),
(self[f"S{m}_P"], dac_p[m]["OUT"]),
(self[f"S{m}_N"], dac_n[m]["OUT"]),
)
def _generate_digital_control(
self,
analog_system: AnalogSystem,
digital_control: NominalDigitalControl,
dither_control_offset: int,
in_high: float,
in_low: float,
out_high: float,
out_low: float,
):
if isinstance(digital_control, NominalDigitalControl):
if digital_control._mulit_phase:
self.Xdc = MultiPhaseDigitalControl(
"Xdc",
analog_system,
digital_control,
in_high,
in_low,
out_high,
out_low,
dither_offset=dither_control_offset,
)
else:
self.Xdc = DigitalControl(
"Xdc",
analog_system,
digital_control,
in_high,
in_low,
out_high,
out_low,
dither_offset=dither_control_offset,
)
else:
raise ValueError(f"Unknown digital control type {type(digital_control)}")
self.connects(
(self["VSS"], self.Xdc["VSS"]),
(self["VDD"], self.Xdc["VDD"]),
(self["CLK"], self.Xdc["CLK"]),
(self["VCM"], self.Xdc["VCM"]),
)
# Connect States
for n in range(analog_system.N):
self.connects(
(self[f"X{n}_P"], self.Xdc[f"X{n}_P"]),
(self[f"X{n}_N"], self.Xdc[f"X{n}_N"]),
)
# Connect inputs
for l in range(analog_system.L):
self.connects(
(self[f"IN{l}_P"], self.Xdc[f"IN{l}_P"]),
(self[f"IN{l}_N"], self.Xdc[f"IN{l}_N"]),
)
# Connect outputs (control signals)
for m in range(analog_system.M):
self.connects(
(self[f"S{m}_P"], self.Xdc[f"S{m}_P"]),
(self[f"S{m}_N"], self.Xdc[f"S{m}_N"]),
)
[docs]class MultiPhaseDigitalControl(SubCircuitElement):
"""The default digital control circuit.
Parameters
----------
instance_name : str
The instance name of the digital control circuit.
analog_system : AnalogSystem
The analog system to which this digital control circuit belongs.
digital_control : MultiPhaseDigitalControl
The digital control circuit to which this digital control circuit belongs.
in_high : float
The high input voltage of the comparator.
in_low : float
The low input voltage of the comparator.
out_high : float
The high output voltage of the comparator.
out_low : float
The low output voltage of the comparator.
dither_offset : int
The offset of the dither control circuit.
"""
def __init__(
self,
instance_name: str,
analog_system: AnalogSystem,
digital_control: NominalDigitalControl,
in_high: float,
in_low: float,
out_high: float,
out_low: float,
dither_offset: int = 0,
):
super().__init__(
instance_name,
"digital_control",
[Terminal("VSS"), Terminal("VDD"), Terminal("CLK"), Terminal("VCM")]
+ [Terminal(f"X{i}_P") for i in range(analog_system.N)]
+ [Terminal(f"X{i}_N") for i in range(analog_system.N)]
+ [Terminal(f"IN{i}_P") for i in range(analog_system.L)]
+ [Terminal(f"IN{i}_N") for i in range(analog_system.L)]
+ [Terminal(f"S{i}_P") for i in range(analog_system.M)]
+ [Terminal(f"S{i}_N") for i in range(analog_system.M)],
)
multi_input_comparator_names = [
f"Xmic_{m}" for m in range(dither_offset, analog_system.M)
]
self.add(
*[
MultiInputComparator(
multi_input_comparator_names[m - dither_offset],
analog_system,
digital_control,
m,
m - dither_offset,
in_high,
in_low,
out_high,
out_low,
)
for m in range(dither_offset, analog_system.M)
]
)
phase_clock_names = [
Terminal(f"CLK_{m}") for m in range(dither_offset, analog_system.M)
]
delay_names = [f"A_delay_{m}" for m in range(dither_offset, analog_system.M)]
self.add(
*[
AnalogDelay(
delay_names[m - dither_offset],
f"analog_delay_{m}",
digital_control._impulse_response[m].t0,
)
for m in range(dither_offset, analog_system.M)
]
)
for m_tilde in range(analog_system.M_tilde):
comparator: MultiInputComparator = self.__getattr__(
multi_input_comparator_names[m_tilde]
)
delay: AnalogDelay = self.__getattr__(delay_names[m_tilde])
self.connects(
(self["CLK"], delay["IN"]),
(self["VDD"], delay["CNTRL"]),
(phase_clock_names[m_tilde], delay["OUT"]),
(phase_clock_names[m_tilde], comparator["CLK"]),
(self["VSS"], comparator["VSS"]),
(self["VDD"], comparator["VDD"]),
(self["VCM"], comparator["VCM"]),
)
# Connect States
for n in range(analog_system.N):
self.connects(
(self[f"X{n}_P"], comparator[f"X{n}_P"]),
(self[f"X{n}_N"], comparator[f"X{n}_N"]),
)
# Connect inputs
for l in range(analog_system.L):
self.connects(
(self[f"IN{l}_P"], comparator[f"IN{l}_P"]),
(self[f"IN{l}_N"], comparator[f"IN{l}_N"]),
)
# Connect outputs (control signals)
for m in range(analog_system.M):
self.connects(
(self[f"S{m}_P"], comparator[f"S{m}_P"]),
(self[f"S{m}_N"], comparator[f"S{m}_N"]),
)
# class ModulatorDigitalControl(SubCircuitElement):
# """The default digital control circuit.
# Parameters
# ----------
# instance_name : str
# The instance name of the digital control circuit.
# analog_system : AnalogSystem
# The analog system to which this digital control circuit belongs.
# digital_control : MultiPhaseDigitalControl
# The digital control circuit to which this digital control circuit belongs.
# in_high : float
# The high input voltage of the comparator.
# in_low : float
# The low input voltage of the comparator.
# out_high : float
# The high output voltage of the comparator.
# out_low : float
# The low output voltage of the comparator.
# dither_offset : int
# The offset of the dither control circuit.
# """
# def __init__(
# self,
# instance_name: str,
# analog_system: AnalogSystem,
# digital_control: NominalModulatorControl,
# in_high: float,
# in_low: float,
# out_high: float,
# out_low: float,
# dither_offset: int = 0,
# ):
# super().__init__(
# instance_name,
# "digital_control",
# [Terminal("VSS"), Terminal("VDD"), Terminal("CLK"), Terminal("VCM")]
# + [Terminal(f"X{i}_P") for i in range(analog_system.N)]
# + [Terminal(f"X{i}_N") for i in range(analog_system.N)]
# + [Terminal(f"IN{i}_P") for i in range(analog_system.L)]
# + [Terminal(f"IN{i}_N") for i in range(analog_system.L)]
# + [Terminal(f"S{i}_P") for i in range(analog_system.M)]
# + [Terminal(f"S{i}_N") for i in range(analog_system.M)],
# )
# multi_input_comparator_names = [
# f"Xmic_{m}" for m in range(dither_offset, analog_system.M)
# ]
# self.add(
# *[
# MultiInputComparator(
# multi_input_comparator_names[m - dither_offset],
# analog_system,
# digital_control,
# m,
# m - dither_offset,
# in_high,
# in_low,
# out_high,
# out_low,
# )
# for m in range(dither_offset, analog_system.M)
# ]
# )
# phase_clock_names = [
# Terminal(f"CLK_{m}") for m in range(dither_offset, analog_system.M)
# ]
# delay_names = [f"A_delay_{m}" for m in range(dither_offset, analog_system.M)]
# self.add(
# *[
# AnalogDelay(
# delay_names[m - dither_offset],
# f"analog_delay_{m}",
# digital_control._phi_1[m],
# )
# for m in range(dither_offset, analog_system.M)
# ]
# )
# for m_tilde in range(analog_system.M_tilde):
# comparator: MultiInputComparator = self.__getattr__(
# multi_input_comparator_names[m_tilde]
# )
# delay: AnalogDelay = self.__getattr__(delay_names[m_tilde])
# self.connects(
# (self["CLK"], delay["IN"]),
# (self["VDD"], delay["CNTRL"]),
# (phase_clock_names[m_tilde], delay["OUT"]),
# (phase_clock_names[m_tilde], comparator["CLK"]),
# (self["VSS"], comparator["VSS"]),
# (self["VDD"], comparator["VDD"]),
# (self["VCM"], comparator["VCM"]),
# )
# # Connect States
# for n in range(analog_system.N):
# self.connects(
# (self[f"X{n}_P"], comparator[f"X{n}_P"]),
# (self[f"X{n}_N"], comparator[f"X{n}_N"]),
# )
# # Connect inputs
# for l in range(analog_system.L):
# self.connects(
# (self[f"IN{l}_P"], comparator[f"IN{l}_P"]),
# (self[f"IN{l}_N"], comparator[f"IN{l}_N"]),
# )
# # Connect outputs (control signals)
# for m in range(analog_system.M):
# self.connects(
# (self[f"S{m}_P"], comparator[f"S{m}_P"]),
# (self[f"S{m}_N"], comparator[f"S{m}_N"]),
# )