Ejemplo n.º 1
0
def gen_model(myfunc,
              order=0,
              numel=512,
              real_type=RealType.FixedPoint,
              func_mode='sync'):
    # create mixed-signal model
    model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type)
    model.add_analog_input('in_')
    model.add_analog_output('out')
    model.add_digital_input('clk')
    model.add_digital_input('rst')

    # create function
    write_tables = (func_mode in {'sync'})
    real_func = model.make_function(myfunc,
                                    domain=[-DOMAIN, +DOMAIN],
                                    order=order,
                                    numel=numel,
                                    write_tables=write_tables)

    # apply function
    model.set_from_func(model.out,
                        real_func,
                        model.in_,
                        clk=model.clk,
                        rst=model.rst,
                        func_mode=func_mode)

    # write the model
    return model.compile_to_file(VerilogGenerator())
Ejemplo n.º 2
0
def gen_model(real_type):
    # create mixed-signal model
    model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type)
    model.add_digital_input('in_', width=N_BITS)
    model.add_analog_output('out')
    model.add_digital_input('clk')
    model.add_digital_input('rst')

    # create function
    domain = [map_f(0), map_f((1 << N_BITS) - 1)]
    real_func = model.make_function(
        lambda x: inv_cdf(unmap_f(x) / (1 << (N_BITS + 1))),
        domain=domain,
        order=1,
        numel=512)

    # apply function
    mapped = compress_uint(model.in_)
    model.set_from_sync_func(model.out,
                             real_func,
                             mapped,
                             clk=model.clk,
                             rst=model.rst)

    # write the model
    return model.compile_to_file(VerilogGenerator())
Ejemplo n.º 3
0
def gen_model(mean=0.0,
              std=1.0,
              num_sigma=6.0,
              order=1,
              numel=512,
              real_type=RealType.FixedPoint):
    # create mixed-signal model
    model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type)
    model.add_digital_input('clk')
    model.add_digital_input('rst')
    model.add_analog_output('real_out')

    # compute the inverse CDF of the distribution (truncated to 0, 1 domain)
    inv_cdf = lambda x: truncnorm.ppf(
        x, -num_sigma, +num_sigma, loc=mean, scale=std)

    # create the function object
    inv_cdf_func = model.make_function(inv_cdf,
                                       domain=[0.0, 1.0],
                                       order=order,
                                       numel=numel)

    model.set_this_cycle(
        model.real_out,
        model.arbitrary_noise(inv_cdf_func, clk=model.clk, rst=model.rst))

    # write the model
    return model.compile_to_file(VerilogGenerator())
Ejemplo n.º 4
0
def gen_model(cap=0.16e-6, ind=0.16e-6, res=0.1, dt=0.01e-6,
              real_type=RealType.FixedPoint):
    # declare model
    m = MixedSignalModel('model', dt=dt, real_type=real_type)
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')
    m.add_digital_input('clk')
    m.add_digital_input('rst')

    # declare system of equations
    m.add_analog_state('i_ind', 10) # TODO: can this be tightened down a bit?
    v_l = AnalogSignal('v_l')
    v_r = AnalogSignal('v_r')
    eqns = [
        Deriv(m.i_ind) == v_l / ind,
        Deriv(m.v_out) == m.i_ind / cap,
        v_r == m.i_ind * res,
        m.v_in == m.v_out + v_l + v_r
    ]
    m.add_eqn_sys(eqns, clk=m.clk, rst=m.rst)

    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    return model_file
Ejemplo n.º 5
0
def gen_model(real_type):
    # declare module
    m = MixedSignalModel('model', real_type=real_type)
    m.add_digital_input('clk')
    m.add_digital_input('rst')
    m.add_analog_output('g')

    # bind expression to internal signal
    m.add_digital_param('param_a')
    m.add_digital_param('param_b')
    m.add_digital_param('param_c', width=2, signed=True)
    m.add_digital_param('param_d', width=2, signed=True)
    m.add_real_param('param_e')
    m.add_real_param('param_f')

    # create state signals
    m.add_digital_state('sig1', init=m.param_a)
    m.add_digital_state('sig2', init=m.param_c, width=2, signed=True)
    m.add_analog_state('sig3', init=m.param_e, range_=25)

    # create main logic
    m.set_next_cycle(m.sig1, m.param_b, clk=m.clk, rst=m.rst)
    m.set_next_cycle(m.sig2, m.param_d, clk=m.clk, rst=m.rst)
    m.set_next_cycle(m.sig3, m.param_f, clk=m.clk, rst=m.rst)

    # sum signals to output
    m.set_this_cycle(m.g, m.sig1 + m.sig2 + m.sig3)

    # compile to a file
    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    # return file location
    return model_file
Ejemplo n.º 6
0
def gen_model(tau, real_type):
    # create mixed-signal model
    m = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type)

    # define I/O
    x = m.add_analog_input('x')
    dt = m.add_analog_input('dt')
    y = m.add_analog_output('y')
    clk = m.add_digital_input('clk')
    rst = m.add_digital_input('rst')

    # create function
    func = m.make_function(lambda t: np.exp(-t / tau),
                           domain=[0, 1e-6],
                           order=1)

    # apply function
    f = m.set_from_sync_func('f', func, dt, clk=clk, rst=rst)

    # update output
    x_prev = m.cycle_delay(x, 1, clk=clk, rst=rst)
    y_prev = m.cycle_delay(y, 1, clk=clk, rst=rst)
    m.set_this_cycle(y, f * y_prev + (1 - f) * x_prev)

    # write the model
    return m.compile_to_file(VerilogGenerator())
Ejemplo n.º 7
0
def main(num=(1e12, ), den=(
    1,
    8e5,
    1e12,
)):
    print('Running model generator...')

    # parse command line arguments
    parser = ArgumentParser()
    parser.add_argument('-o', '--output', type=str)
    parser.add_argument('--dt', type=float)
    args = parser.parse_args()

    # create the model
    model = MixedSignalModel('filter',
                             AnalogInput('v_in'),
                             AnalogOutput('v_out'),
                             dt=args.dt)
    model.set_tf(input_=model.v_in, output=model.v_out, tf=(num, den))

    # determine the output filename
    filename = os.path.join(get_full_path(args.output),
                            f'{model.module_name}.sv')
    print('Model will be written to: ' + filename)

    # generate the model
    model.compile_to_file(VerilogGenerator(), filename)
Ejemplo n.º 8
0
def main(tau=1e-6):
    print('Running model generator...')

    # parse command line arguments
    parser = ArgumentParser()
    parser.add_argument('-o', '--output', type=str)
    parser.add_argument('--dt', type=float)
    args = parser.parse_args()

    # create the model
    m = MixedSignalModel('filter', dt=args.dt)

    m.add_analog_input('v_in')
    m.add_analog_output('v_out')

    c = m.make_circuit()
    gnd = c.make_ground()

    c.voltage('net_v_in', gnd, m.v_in)
    c.diode('net_v_in', 'net_v_x', vf=0)
    c.resistor('net_v_x', 'net_v_out', 1e3)
    v_out = c.capacitor('net_v_out', gnd, 1e-9, voltage_range=1.5)

    m.set_this_cycle(m.v_out, v_out)

    # determine the output filename
    filename = os.path.join(get_full_path(args.output), f'{m.module_name}.sv')
    print('Model will be written to: ' + filename)

    # generate the model
    m.compile_to_file(VerilogGenerator(), filename)
Ejemplo n.º 9
0
def gen_model(r_off=2.6e3, current_range=100, real_type=RealType.FixedPoint):
    # declare model
    m = MixedSignalModel('model', dt=1e-9, real_type=real_type)
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')
    m.add_digital_input('sw1')
    m.add_digital_input('sw2')
    m.add_digital_input('clk')
    m.add_digital_input('rst')

    # create test circuit
    c = m.make_circuit(clk=m.clk, rst=m.rst)
    gnd = c.make_ground()
    c.voltage('net_v_in', gnd, m.v_in)
    c.switch('net_v_in', 'net_v_x', m.sw1, r_off=r_off)
    c.switch('net_v_x', gnd, m.sw2, r_off=r_off)
    c.inductor('net_v_in', 'net_v_x', 1.0, current_range=current_range)
    c.add_eqns(AnalogSignal('net_v_x') == m.v_out)

    # compile to a file
    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    # return file location
    return model_file
Ejemplo n.º 10
0
def gen_model(rp1, rn1, rp2, rn2, real_type, dt=0.1e-6):
    # declare model
    m = MixedSignalModel('model', dt=dt, real_type=real_type)

    # declare I/O
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')
    m.add_digital_input('sw1')
    m.add_digital_input('sw2')

    # declare switch circuit
    c = m.make_circuit()
    gnd = c.make_ground()
    c.voltage('net_v_in', gnd, m.v_in)
    c.switch('net_v_in', 'net_v_x', m.sw1, r_on=rp1, r_off=rn1)
    c.switch('net_v_x', gnd, m.sw2, r_on=rp2, r_off=rn2)
    c.add_eqns(AnalogSignal('net_v_x') == m.v_out)

    # compile to a file
    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    # return file location
    return model_file
Ejemplo n.º 11
0
def gen_model(real_vals, sint_vals, uint_vals, addr_bits, sint_bits, uint_bits,
              real_type):
    # create mixed-signal model
    model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type)
    model.add_digital_input('addr', width=addr_bits)
    model.add_digital_input('clk')
    model.add_analog_output('real_out')
    model.add_digital_output('sint_out', width=sint_bits)
    model.add_digital_output('uint_out', width=uint_bits)

    # create tables
    real_table = model.make_real_table(real_vals)
    sint_table = model.make_sint_table(sint_vals)
    uint_table = model.make_uint_table(uint_vals)

    # assign values
    model.set_from_sync_rom(model.real_out,
                            real_table,
                            model.addr,
                            clk=model.clk)
    model.set_from_sync_rom(model.sint_out,
                            sint_table,
                            model.addr,
                            clk=model.clk)
    model.set_from_sync_rom(model.uint_out,
                            uint_table,
                            model.addr,
                            clk=model.clk)

    # write the model
    return model.compile_to_file(VerilogGenerator())
Ejemplo n.º 12
0
def main():
    model = MixedSignalModel('model')
    model.add_analog_input('a')
    model.add_analog_input('b')

    model.bind_name('c', model.a + model.b)

    model.compile_and_print(VerilogGenerator())
Ejemplo n.º 13
0
    def __init__(self,  filename=None, **system_values):
        # set a fixed random seed for repeatability
        np.random.seed(2)

        module_name = Path(filename).stem
        build_dir   = Path(filename).parent

        print(f'Running model generator for {module_name}...')
        assert (all([req_val in system_values for req_val in self.required_values()])), \
            f'Cannot build {module_name}, Missing parameter in config file'

        m = MixedSignalModel(module_name, dt=system_values['dt'], build_dir=build_dir,
                             real_type=get_dragonphy_real_type())
        m.add_real_param('t_del', 0)
        m.add_digital_input('emu_rst')
        m.add_digital_input('emu_clk')
        m.add_analog_input('t_lo')
        m.add_analog_input('t_hi')
        m.add_analog_input('emu_dt')
        m.add_analog_output('dt_req', init=m.t_del)
        m.add_digital_output('clk_val')

        # determine if the request was granted
        m.bind_name('req_grant', m.dt_req == m.emu_dt)

        # update the clock value
        m.add_digital_state('prev_clk_val')
        m.set_next_cycle(m.prev_clk_val, m.clk_val, clk=m.emu_clk, rst=m.emu_rst)
        m.set_this_cycle(m.clk_val, if_(m.req_grant, ~m.prev_clk_val, m.prev_clk_val))

        # determine arguments for formating time steps
        # TODO: clean this up
        dt_fmt_kwargs = dict(
            range_=m.emu_dt.format_.range_,
            width=m.emu_dt.format_.width,
            exponent=m.emu_dt.format_.exponent
        )
        array_fmt_kwargs = deepcopy(dt_fmt_kwargs)
        array_fmt_kwargs['real_range_hint'] = m.emu_dt.format_.range_
        del array_fmt_kwargs['range_']

        # determine the next period
        dt_req_next_array = array([m.t_hi, m.t_lo], m.prev_clk_val, **array_fmt_kwargs)
        m.bind_name('dt_req_next', dt_req_next_array, **dt_fmt_kwargs)

        # increment the time request
        m.bind_name('dt_req_incr', m.dt_req - m.emu_dt, **dt_fmt_kwargs)

        # determine the next period
        dt_req_imm_array = array([m.dt_req_incr, m.dt_req_next], m.req_grant, **array_fmt_kwargs)
        m.bind_name('dt_req_imm', dt_req_imm_array, **dt_fmt_kwargs)
        m.set_next_cycle(m.dt_req, m.dt_req_imm, clk=m.emu_clk, rst=m.emu_rst)

        # generate the model
        m.compile_to_file(VerilogGenerator())

        self.generated_files = [filename]
Ejemplo n.º 14
0
def test_distribute_mult():
    a = AnalogSignal('a')
    b = AnalogSignal('b')
    c = AnalogSignal('c')
    d = AnalogSignal('d')

    e = a + 3.4 * (b + 5.6 * (c + 7.8 * d))
    print('Original expression:')
    print(e)
    print('')

    f = distribute_mult(e)
    print('Flattened expresion:')
    print(f)
    print('')

    v = VerilogGenerator()
    v.text = ''
    v.expr_to_signal(f)
    print('Compiled expression:')
    print(v.text)
    print('')

    # check that the flattened expression is OK
    assert (isinstance(f, Sum))
    res = {}
    for op in f.operands:
        if isinstance(op, Product):
            subops = op.operands
            sig = subops[0] if isinstance(subops[0],
                                          AnalogSignal) else subops[1]
            val = subops[1] if isinstance(subops[0],
                                          AnalogSignal) else subops[0]
            res[sig.name] = val.value
        elif isinstance(op, AnalogSignal):
            res[op.name] = 1.0
    print('Dictionary mapping signal names to coefficients:')
    print(res)
    assert len(res) == 4
    assert isclose(res['a'], 1)
    assert isclose(res['b'], 3.4)
    assert isclose(res['c'], 3.4 * 5.6)
    assert isclose(res['d'], 3.4 * 5.6 * 7.8)
Ejemplo n.º 15
0
def main():
    tau = 1e-6
    dt = 0.1e-6

    model = MixedSignalModel('model', dt=dt)
    model.add_analog_input('v_in')
    model.add_analog_output('v_out', init=1.23)

    model.add_eqn_sys([Deriv(model.v_out) == (model.v_in - model.v_out)/tau])

    model.compile_and_print(VerilogGenerator())
Ejemplo n.º 16
0
def main():
    dt = 0.1e-6

    m = MixedSignalModel('model', dt=dt)

    m.add_analog_input('v_in')
    m.add_analog_output('v_out')

    m.add_eqn_sys([m.v_out == 0.123 * m.v_in])

    m.compile_and_print(VerilogGenerator())
Ejemplo n.º 17
0
def main():
    a = AnalogSignal('a')
    b = AnalogSignal('b')
    c = AnalogSignal('c')
    d = AnalogSignal('d')

    e = 1.2 * (a + 3.4 * (b + 5.6 * (c + 7.8 * d)))

    print('Original expression:')
    print(e)
    print('')

    print('Expression after flattening:')
    print(distribute_mult(e))
    print('')

    print('Compiled expression')
    v = VerilogGenerator()
    v.text = ''
    v.expr_to_signal(distribute_mult(e))
    print(v.text)
Ejemplo n.º 18
0
def main():
    model = MixedSignalModel('model')
    model.add_analog_input('a')
    model.add_digital_input('b', width=8)
    model.add_digital_output('c', width=12)

    model.bind_name('d', model.a + model.b)

    clamped = clamp(to_sint(model.d, width=model.c.width + 1), 0, 1023)
    model.set_next_cycle(model.c, to_uint(clamped, width=model.c.width))

    model.compile_and_print(VerilogGenerator())
Ejemplo n.º 19
0
Archivo: tf.py Proyecto: xlchan/msdsl
def main():
    dt = 0.1e-6

    num = (1e12,)
    den = (1, 8e5, 1e12,)

    model = MixedSignalModel('model', dt=dt)
    model.add_analog_input('v_in')
    model.add_analog_output('v_out')

    model.set_tf(input_=model.v_in, output=model.v_out, tf=(num, den))

    model.compile_and_print(VerilogGenerator())
Ejemplo n.º 20
0
def test_tanh(simulator, real_type, err_lim=2.5e-4):
    # set the random seed for repeatable results
    np.random.seed(0)

    # generate model
    model = SaturationModel(module_name='model', build_dir=BUILD_DIR, real_type=real_type)
    model_file = model.compile_to_file(VerilogGenerator())

    # declare circuit
    class dut(m.Circuit):
        name = 'test_tanh'
        io = m.IO(
            in_=fault.RealIn,
            out=fault.RealOut
        )

    # create the tester
    tester = MsdslTester(dut)

    # save the outputs
    inpts = np.random.uniform(-2, +2, 100)
    apprx = []
    for in_ in inpts:
        tester.poke(dut.in_, in_)
        tester.eval()
        apprx.append(tester.get_value(dut.out))

    # run the simulation
    parameters = {
        'in_range': 2.5,
        'out_range': 2.5
    }
    tester.compile_and_run(
        directory=BUILD_DIR,
        simulator=simulator,
        ext_srcs=[model_file, get_file('tanh/test_tanh.sv')],
        parameters=parameters,
        real_type=real_type
    )

    # evaluate the outputs
    apprx = np.array([elem.value for elem in apprx], dtype=float)

    # compute the exact response to inputs
    exact = model.func(inpts)

    # check the result
    err = np.sqrt(np.mean((exact-apprx)**2))
    print(f'RMS error: {err}')
    assert err <= err_lim
Ejemplo n.º 21
0
def main():
    # define ports
    m = MixedSignalModel('comparator')
    m.add_analog_input('in_p')
    m.add_analog_input('in_n')
    m.add_digital_output('out', init=0)
    m.add_digital_input('clk')

    # define behavior
    m.immediate_assign('out_async', m.in_p > m.in_n)
    m.next_cycle_assign(m.out, m.out_async, clk=m.clk)

    # write model
    m.compile_and_print(VerilogGenerator())
Ejemplo n.º 22
0
def test_check_format(in_type, in_opt, out_type, out_opt, check_format, cycle,
                      expected_result, init_val):
    # declare model I/O
    m = MixedSignalModel('model')

    if in_type == 'uint':
        m.add_digital_input('a', width=in_opt)
    elif in_type == 'sint':
        m.add_digital_input('a', width=in_opt, signed=True)
    elif in_type == 'real':
        m.add_analog_input('a')
    else:
        raise Exception(f'Invalid in_type: {in_type}')

    if out_type == 'uint':
        m.add_digital_state('y', width=out_opt, init=init_val)
    elif out_type == 'sint':
        m.add_digital_state('y', width=out_opt, signed=True, init=init_val)
    elif out_type == 'real':
        m.add_analog_state('y', range_=out_opt)
    else:
        raise Exception(f'Invalid out_type: {out_type}')

    if cycle == 'this':
        m.set_this_cycle(m.y, m.a, check_format=check_format)
    elif cycle == 'next':
        m.set_next_cycle(m.y, m.a, check_format=check_format)
    else:
        raise Exception(f'Invalid cycle type: {cycle}')

    # compile to a file
    if expected_result is not None:
        with pytest.raises(Exception) as e:
            m.compile(VerilogGenerator())
        assert expected_result in str(e.value)
    else:
        m.compile(VerilogGenerator())
Ejemplo n.º 23
0
def gen_model(const=1.23, real_type=RealType.FixedPoint):
    # declare module
    m = MixedSignalModel('model', real_type=real_type)
    m.add_analog_input('a')
    m.add_analog_output('b')

    m.add_eqn_sys([m.b == const * m.a])

    # compile to a file
    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    # return file location
    return model_file
Ejemplo n.º 24
0
def main():
    tau = 1e-6
    dt = 0.1e-6

    model = MixedSignalModel('model', dt=dt)
    model.add_analog_input('v_in')
    model.add_analog_output('v_out')
    model.add_digital_input('ctrl')

    model.add_eqn_sys([
        Deriv(
            model.v_out) == eqn_case([0, 1 / tau], [model.ctrl]) * model.v_in -
        model.v_out / tau
    ])

    model.compile_and_print(VerilogGenerator())
Ejemplo n.º 25
0
def gen_model(tau, dt, real_type):
    model = MixedSignalModel('model', dt=dt, real_type=real_type)
    model.add_analog_input('v_in')
    model.add_analog_output('v_out')
    model.add_digital_input('clk')
    model.add_digital_input('rst')

    model.add_eqn_sys([Deriv(model.v_out) == (model.v_in - model.v_out) / tau],
                      clk=model.clk,
                      rst=model.rst)

    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    model.compile_to_file(VerilogGenerator(), filename=model_file)

    return model_file
Ejemplo n.º 26
0
def gen_model(real_type):
    # declare module
    m = MixedSignalModel('model', real_type=real_type)
    m.add_analog_input('a')
    m.add_analog_input('b')

    # bind expression to internal signal
    m.bind_name('c', m.a + m.b)

    # compile to a file
    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    # return file location
    return model_file
Ejemplo n.º 27
0
Archivo: det.py Proyecto: xlchan/msdsl
def main():
    tau_det_fast = 1e-9
    tau_det_slow = 360e-9
    dt = 4.6e-9

    m = MixedSignalModel('model', dt=dt)
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')

    m.bind_name('in_gt_out', m.v_in > m.v_out)

    # detector dynamics
    m.add_eqn_sys([
        Deriv(m.v_out) == eqn_case([0, 1 / tau_det_fast], [m.in_gt_out]) * (m.v_in - m.v_out) - (m.v_out / tau_det_slow)
    ])

    m.compile_and_print(VerilogGenerator())
Ejemplo n.º 28
0
def main():
    print('Running model generator...')

    # parse command line arguments
    parser = ArgumentParser()
    parser.add_argument('-o', '--output', type=str)
    parser.add_argument('--dt', type=float)
    args = parser.parse_args()

    # create the model
    model = Filter(dt=args.dt)

    # determine the output filename
    filename = os.path.join(get_full_path(args.output), f'{model.module_name}.sv')
    print('Model will be written to: ' + filename)

    # generate the model
    model.compile_to_file(VerilogGenerator(), filename)
Ejemplo n.º 29
0
def gen_model():
    # declare model I/O
    m = MixedSignalModel('model')
    m.add_digital_input('a', width=63, signed=True)
    m.add_digital_input('b', width=63, signed=True)
    m.add_digital_output('c', width=64, signed=True)

    # assign expression to output
    m.bind_name('d', m.a - m.b)
    m.set_this_cycle(m.c, m.d)

    # compile to a file
    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    # return file location
    return model_file
Ejemplo n.º 30
0
def gen_model(tau=1e-6, dt=0.1e-6, real_type=RealType.FixedPoint):
    m = MixedSignalModel('model', dt=dt, real_type=real_type)
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')
    m.add_digital_input('clk')
    m.add_digital_input('rst')

    m.set_tf(input_=m.v_in,
             output=m.v_out,
             tf=((1, ), (tau, 1)),
             clk=m.clk,
             rst=m.rst)

    BUILD_DIR.mkdir(parents=True, exist_ok=True)
    model_file = BUILD_DIR / 'model.sv'
    m.compile_to_file(VerilogGenerator(), filename=model_file)

    return model_file