Source code for cbadc.circuit.components.comparator

from typing import Dict, List, Set
from .. import (
    CircuitElement,
    SPICE_VALUE,
    DeviceModel,
    Port,
    Terminal,
    SubCircuitElement,
    _template_env,
)
from ..models.comparator import (
    ADC_Bridge_Model,
    D_Flip_Flop_Model,
    DAC_Bridge_Model,
)
from . import ngspice_vector_terminal_vector_vector


[docs]class ADCBridgeRelative(CircuitElement): def __init__( self, instance_name: str, model_name: str, in_low: SPICE_VALUE, in_high: SPICE_VALUE, rise_delay: SPICE_VALUE = 1e-9, fall_delay: SPICE_VALUE = 1e-9, comments: List[str] = [], ): if not instance_name or not isinstance(instance_name, str): raise TypeError(f'Expected str, got {type(instance_name)}') elif instance_name[0] != 'A': instance_name = 'A' + instance_name super().__init__( instance_name, [ Terminal('IN'), Terminal('OUT'), Terminal('VCM'), ], comments=comments, ) self.model = ADC_Bridge_Model( model_name, in_low=in_low, in_high=in_high, rise_delay=rise_delay, fall_delay=fall_delay, comments=comments, )
[docs] def get_ngspice(self, connections: Dict[Terminal, Port]) -> str: return _template_env.get_template('ngspice/xspice.cir.j2').render( { 'instance_name': self.instance_name, 'terminals': self._adc_bridge_get_terminal_names(connections), 'parameters': self._parameters_dict, 'comments': self.comments, 'model_instance_name': self.model.model_name, } )
def _adc_bridge_get_terminal_names( self, connections: Dict[Terminal, Port] ) -> List[str]: named_nodes = self._get_terminal_names(connections) return [f'[%vd({named_nodes[0]},{named_nodes[2]})]', f'[{named_nodes[1]}]']
[docs]class ADCBridgeAbsolute(ADCBridgeRelative): def _adc_bridge_get_terminal_names( self, connections: Dict[Terminal, Port] ) -> List[str]: named_nodes = self._get_terminal_names(connections) return [f'[{named_nodes[0]}]', f'[{named_nodes[1]}]']
[docs]class DAC_Bridge(CircuitElement): def __init__( self, instance_name: str, model_name: str, out_low: SPICE_VALUE, out_high: SPICE_VALUE, out_undef: SPICE_VALUE, input_load: SPICE_VALUE = 1e-12, t_rise: SPICE_VALUE = 1e-9, t_fall: SPICE_VALUE = 1e-9, comments: List[str] = [], ): if not instance_name or not isinstance(instance_name, str): raise TypeError(f'Expected str, got {type(instance_name)}') elif instance_name[0] != 'A': instance_name = 'A' + instance_name super().__init__( instance_name, [Terminal('IN'), Terminal('OUT')], comments=comments, ) self.model = DAC_Bridge_Model( model_name, out_low=out_low, out_high=out_high, out_undef=out_undef, input_load=input_load, t_rise=t_rise, t_fall=t_fall, comments=comments, )
[docs] def get_ngspice(self, connections: Dict[Terminal, Port]) -> str: return _template_env.get_template('ngspice/xspice.cir.j2').render( { 'instance_name': self.instance_name, 'terminals': ngspice_vector_terminal_vector_vector( self._get_terminal_names(connections) ), 'parameters': self._parameters_dict, 'comments': self.comments, 'model_instance_name': self.model.model_name, } )
[docs]class D_FLIP_FLOP(CircuitElement): def __init__( self, instance_name: str, model_name: str, clk_delay: SPICE_VALUE = 0.0, set_delay: SPICE_VALUE = 0.0, reset_delay: SPICE_VALUE = 0.0, ic: SPICE_VALUE = 2, rise_delay: SPICE_VALUE = 0.0, fall_delay: SPICE_VALUE = 0.0, comments: List[str] = [], ): if not instance_name or not isinstance(instance_name, str): raise TypeError(f'Expected str, got {type(instance_name)}') elif instance_name[0] != 'A': instance_name = 'A' + instance_name super().__init__( instance_name, [ Terminal('IN'), Terminal('CLK'), Terminal('SET'), Terminal('RES'), Terminal('F_OUT_P'), Terminal('F_OUT_N'), ], comments=comments, ) self.model = D_Flip_Flop_Model( model_name, clk_delay=clk_delay, set_delay=set_delay, reset_delay=reset_delay, ic=ic, rise_delay=rise_delay, fall_delay=fall_delay, comments=comments, )
[docs] def get_ngspice(self, connections: Dict[Terminal, Port]) -> str: return _template_env.get_template('ngspice/xspice.cir.j2').render( { 'instance_name': self.instance_name, 'terminals': self._get_terminal_names(connections), 'parameters': self._parameters_dict, 'comments': self.comments, 'model_instance_name': self.model.model_name, } )
[docs]class ClockedComparator(SubCircuitElement): def __init__( self, instance_name: str, sub_ckt_name: str, in_low: SPICE_VALUE, in_high: SPICE_VALUE, out_low: SPICE_VALUE, out_high: SPICE_VALUE, out_undef: SPICE_VALUE, input_load: SPICE_VALUE = 1e-12, clk_delay: SPICE_VALUE = 0.0, clk_offset: SPICE_VALUE = 0.6, t_tolerance: SPICE_VALUE = 0.0, t_rise: SPICE_VALUE = 1e-9, t_fall: SPICE_VALUE = 1e-9, rise_delay: SPICE_VALUE = 1e-15, fall_delay: SPICE_VALUE = 1e-15, set_delay: SPICE_VALUE = 1e-15, reset_delay: SPICE_VALUE = 1e-15, comments: List[str] = [], ): super().__init__( instance_name, sub_ckt_name, [Terminal('CLK'), Terminal('VCM'), Terminal('IN'), Terminal('OUT')], ) self.add( ADCBridgeRelative( 'Aclk_adc', 'adc', in_low, in_high, rise_delay=rise_delay, fall_delay=fall_delay, ), ADCBridgeRelative( 'Ain_adc', 'adc', in_low, in_high, rise_delay=rise_delay, fall_delay=fall_delay, ), D_FLIP_FLOP( 'Adffp', 'dflip', clk_delay, set_delay=set_delay, reset_delay=reset_delay, ic=1, rise_delay=rise_delay, fall_delay=fall_delay, ), DAC_Bridge( 'Adac', 'dac', out_low, out_high, out_undef, input_load, t_rise, t_fall, ), ) CLKD = Terminal('CLKD') self.connects( (self['CLK'], self.Aclk_adc['IN']), (self['VCM'], self.Aclk_adc['VCM']), (self['IN'], self.Ain_adc['IN']), (self['VCM'], self.Ain_adc['VCM']), (self['OUT'], self.Adac['OUT']), (CLKD, self.Adffp['CLK']), (CLKD, self.Aclk_adc['OUT']), (self.Ain_adc['OUT'], self.Adffp['IN']), (self.Adffp['F_OUT_P'], self.Adac['IN']), ) # overwrite the get_model_set method to return the model set def _get_model_set(self, verilog_ams=False) -> List[DeviceModel]: if verilog_ams: return [self.get_verilog_ams()] else: return super()._get_model_set(verilog_ams) def get_verilog_ams(self) -> DeviceModel: raise NotImplementedError() return _template_env.get_template( 'verilog_ams/clocked_comparator.vams.j2' ).render( { 'module_instance_name': self.model_name, 'model_name': self.ng_spice_model_name, 'parameters': self.parameters, 'description': 'A ternary clocked comparator', 'terminals': ['clk', 'in', 'out'], } )
[docs] def get_spectre(self, connections: Dict[Terminal, Port]): return _template_env.get_template('spectre/verilog_ams.cir.j2').render( { 'instance_name': self.instance_name, 'terminals': self._get_terminal_names(connections), 'comments': self.comments, 'model_instance_name': self.model.model_name, } )
def _get_spectre_sub_circuit_definition(self) -> List[str]: # no subcircuit for verilog ams spectre. return []
[docs]class DifferentialOutputClockedComparator(SubCircuitElement): def __init__( self, instance_name: str, sub_ckt_name: str, in_low: SPICE_VALUE, in_high: SPICE_VALUE, out_low: SPICE_VALUE, out_high: SPICE_VALUE, out_undef: SPICE_VALUE, input_load: SPICE_VALUE = 1e-12, clk_delay: SPICE_VALUE = 0.0, clk_offset: SPICE_VALUE = 0.6, t_tolerance: SPICE_VALUE = 0.0, t_rise: SPICE_VALUE = 1e-15, t_fall: SPICE_VALUE = 1e-15, rise_delay: SPICE_VALUE = 1e-15, fall_delay: SPICE_VALUE = 1e-15, set_delay: SPICE_VALUE = 1e-15, reset_delay: SPICE_VALUE = 1e-15, comments: List[str] = [], ): super().__init__( instance_name, sub_ckt_name, [ Terminal('CLK'), Terminal('IN'), Terminal('OUT_P'), Terminal('OUT_N'), Terminal('VCM'), ], ) self.add( ADCBridgeRelative( 'Aclk_adc', 'adc', in_low, in_high, rise_delay=rise_delay, fall_delay=fall_delay, ), ADCBridgeRelative( 'Ain_adc', 'adc', in_low, in_high, rise_delay=rise_delay, fall_delay=fall_delay, ), D_FLIP_FLOP( 'Adffp', 'dflip', clk_delay, set_delay=set_delay, reset_delay=reset_delay, ic=1, rise_delay=rise_delay, fall_delay=fall_delay, ), DAC_Bridge( 'Adac_p', 'dac', out_low, out_high, out_undef, input_load, t_rise, t_fall, ), DAC_Bridge( 'Adac_n', 'dac', out_low, out_high, out_undef, input_load, t_rise, t_fall, ), ) CLKD = Terminal('CLKD') self.connects( (self['CLK'], self.Aclk_adc['IN']), (self['VCM'], self.Aclk_adc['VCM']), (self['IN'], self.Ain_adc['IN']), (self['VCM'], self.Ain_adc['VCM']), (self['OUT_P'], self.Adac_p['OUT']), (self['OUT_N'], self.Adac_n['OUT']), (CLKD, self.Adffp['CLK']), (CLKD, self.Aclk_adc['OUT']), (self.Ain_adc['OUT'], self.Adffp['IN']), (self.Adffp['F_OUT_P'], self.Adac_p['IN']), (self.Adffp['F_OUT_N'], self.Adac_n['IN']), ) # overwrite the get_model_set method to return the model set def _get_model_set(self, verilog_ams=False) -> List[DeviceModel]: if verilog_ams: return [self.get_verilog_ams()] else: return super()._get_model_set(verilog_ams)
[docs] def get_spectre(self, connections: Dict[Terminal, Port]): raise NotImplementedError return _template_env.get_template('spectre/verilog_ams.cir.j2').render( { 'instance_name': self.instance_name, 'terminals': self._get_terminal_names(connections), 'comments': self.comments, 'model_instance_name': self.model.model_name, } )
def _get_spectre_sub_circuit_definition(self) -> List[str]: # no subcircuit for verilog ams spectre. return [] def get_verilog_ams(self) -> DeviceModel: raise NotImplementedError() return _template_env.get_template( 'verilog_ams/clocked_comparator.vams.j2' ).render( { 'module_instance_name': self.model_name, 'model_name': self.ng_spice_model_name, 'parameters': self.parameters, 'description': 'A ternary clocked comparator', 'terminals': ['clk', 'in', 'out'], } )