Esempio n. 1
0
def duc(clearn, dac_clock, dac2x_clock, loopen, loopback, fifo_empty, fifo_re,
        fifo_dvld, fifo_rdata, fifo_underflow, system_txen, system_txstop,
        system_ddsen, system_filteren, system_interp, system_shift, system_fcw,
        system_correct_i, system_correct_q, system_gain_i, system_gain_q,
        underrun, sample, dac_en, dac_data, dac_last, rx_fifo_full, rx_fifo_we,
        rx_fifo_wdata, rxen, rxstop, rxfilteren, decim, system_rx_correct_i,
        system_rx_correct_q, rx_overrun, rx_sample, adc_idata, adc_qdata,
        adc_last, fir_coeff_ram_addr, fir_coeff_ram_din0, fir_coeff_ram_din1,
        fir_coeff_ram_blk, fir_coeff_ram_wen, fir_coeff_ram_dout0,
        fir_coeff_ram_dout1, fir_delay_line_i_ram_addr,
        fir_delay_line_i_ram_din, fir_delay_line_i_ram_blk,
        fir_delay_line_i_ram_wen, fir_delay_line_i_ram_dout,
        fir_delay_line_q_ram_addr, fir_delay_line_q_ram_din,
        fir_delay_line_q_ram_blk, fir_delay_line_q_ram_wen,
        fir_delay_line_q_ram_dout, system_firen, system_fir_bank1,
        system_fir_bank0, system_fir_N, **kwargs):
    """The Digital Up Converter.    

    :param clearn: Reset signal, completely resets the dsp chain.
    :param dac_clock: The sampling clock.
    :param dac2x_clock: Twice the sampling clock.
    :param loopen: Enable the loopback device.
    :param loopback: The loopback signature to the digital down converter.
    :param fifo_empty: Input signal that the fifo is empty.
    :param fifo_re: Output signal to enable a sample read.
    :param fifo_dvld: Input signal that FIFO data is valid.
    :param fifo_rdata: Input sample data.
    :param fifo_underflow: Input signal that fifo underflowed.
    :param system_txen: Enable transmit.
    :param system_txstop: Stop the transmitter.
    :param system_ddsen: Enable the DDS.
    :param system_filteren: Enable the CIC filter.
    :param system_interp: Interpolation rate.
    :param system_fcw: Set the frequency control word of the DDS.
    :param system_correct_i: Set the i-Channel AQM DC Offset Correction.
    :param system_correct_q: Set the q-Channel AQM DC Offset Correction.
    :param system_gain_i: Set the i-channel AQM gain correction.
    :param system_gain_q: Set the q-channel AQM gain correction.
    :param underrun: Output of number of underruns to RFE.
    :param sample: The sample.
    :param dac_en: Enable DAC on valid data signal.
    :param dac_data: The interleaved DAC data.
    :param dac_last: The last sample going out on the DAC, stops the transmit.
    :returns: A MyHDL synthesizable module.
    """

    dspsim = kwargs.get('dspsim', None)

    # DIGIAL UP CONVERTER
    interp_default = kwargs.get('interp', 1)

    sync_txen = Signal(bool(0))
    txen = Signal(bool(0))
    sync_txstop = Signal(bool(0))
    txstop = Signal(bool(0))
    sync_ddsen = Signal(bool(0))
    ddsen = Signal(bool(0))
    sync_filteren = Signal(bool(0))
    filteren = Signal(bool(0))
    sync_interp = Signal(intbv(interp_default)[len(system_interp):])
    interp = Signal(intbv(interp_default)[len(system_interp):])
    sync_shift = Signal(intbv(0)[len(system_shift):])
    shift = Signal(intbv(0)[len(system_shift):])
    sync_firen = Signal(bool(0))
    firen = Signal(bool(0))
    sync_fir_bank0 = Signal(bool(0))
    fir_bank0 = Signal(bool(0))
    sync_fir_bank1 = Signal(bool(0))
    fir_bank1 = Signal(bool(0))
    sync_fir_N = Signal(intbv(0, min=system_fir_N.min, max=system_fir_N.max))
    fir_N = Signal(intbv(0, min=system_fir_N.min, max=system_fir_N.max))
    sync_fcw = Signal(intbv(0)[len(system_fcw):])
    fcw = Signal(intbv(0)[len(system_fcw):])
    sync_correct_i = Signal(intbv(0)[len(system_correct_i):])
    correct_i = Signal(intbv(0)[len(system_correct_i):])
    sync_correct_q = Signal(intbv(0)[len(system_correct_q):])
    correct_q = Signal(intbv(0)[len(system_correct_q):])
    sync_gain_i = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    gain_i = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    sync_gain_q = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    gain_q = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    sync_rx_correct_i = Signal(intbv(0)[len(system_rx_correct_i):])
    rx_correct_i = Signal(intbv(0)[len(system_rx_correct_i):])
    sync_rx_correct_q = Signal(intbv(0)[len(system_rx_correct_q):])
    rx_correct_q = Signal(intbv(0)[len(system_rx_correct_q):])

    sample_valid = sample.valid
    sample_last = sample.last
    sample_i = sample.i
    sample_q = sample.q

    rx_sample_valid = rx_sample.valid
    rx_sample_last = rx_sample.last
    rx_sample_i = rx_sample.i
    rx_sample_q = rx_sample.q

    adc_sample = Signature("adc",
                           True,
                           bits=10,
                           valid=rxen,
                           last=adc_last,
                           i=adc_idata,
                           q=adc_qdata)

    truncated_1 = Signature("truncated1", True, bits=9)
    truncator_1 = truncator(clearn, dac_clock, sample, truncated_1)
    duc_chain = (truncator_1, )

    if kwargs.get('dds_enable', True):
        if_out = Signature("if_out", True, bits=9)
        dds_args = clearn, dac_clock, ddsen, truncated_1, if_out, fcw
        dds = DDS(*dds_args, num_samples=DDS_NUM_SAMPLES)
        duc_chain = duc_chain + (dds, )
    else:
        if_out = truncated_1

    if kwargs.get('fir_enable', True):
        filtered = Signature("filtered", True, bits=9)
        fir_0 = FIR(clearn, dac_clock, if_out, filtered, fir_coeff_ram_addr,
                    fir_coeff_ram_din0, fir_coeff_ram_din1, fir_coeff_ram_blk,
                    fir_coeff_ram_wen, fir_coeff_ram_dout0,
                    fir_coeff_ram_dout1, fir_delay_line_i_ram_addr,
                    fir_delay_line_i_ram_din, fir_delay_line_i_ram_blk,
                    fir_delay_line_i_ram_wen, fir_delay_line_i_ram_dout,
                    fir_delay_line_q_ram_addr, fir_delay_line_q_ram_din,
                    fir_delay_line_q_ram_blk, fir_delay_line_q_ram_wen,
                    fir_delay_line_q_ram_dout, firen, fir_bank1, fir_bank0,
                    fir_N)
        duc_chain = duc_chain + (fir_0, )
    else:
        filtered = if_out

    upsampled = Signature("upsampled", True, bits=9)
    upsampler_0 = upsampler(clearn, dac_clock, filtered, upsampled, interp)
    duc_chain = duc_chain + (upsampler_0, )

    if kwargs.get('cic_enable', True):
        rate_changed = Signature("rate_changed", True, bits=10)
        cic_0 = cic(clearn,
                    dac_clock,
                    filtered,
                    rate_changed,
                    interp,
                    shift,
                    cic_order=kwargs.get('cic_order', 4),
                    cic_delay=kwargs.get('cic_delay', 1),
                    sim=dspsim)
        duc_chain = duc_chain + (cic_0, )

        processed = Signature("processed", True, bits=10)
        processed_mux = iqmux(clearn, dac_clock, filteren, upsampled,
                              rate_changed, processed)
        duc_chain = duc_chain + (processed_mux, )
    else:
        processed = upsampled

    rf_out = processed

    tx_loopback = pass_through_with_enable(clearn, dac_clock, rf_out, loopback,
                                           loopen)
    duc_chain = duc_chain + (tx_loopback, )

    if kwargs.get('conditioning_enable', True):
        gain_corrected = Signature("gain_corrected", True, bits=10)
        gain_corrector_0 = gain_corrector(clearn, dac_clock, gain_i, gain_q,
                                          rf_out, gain_corrected)
        duc_chain = duc_chain + (gain_corrector_0, )

        corrected = Signature("offset_corrected", True, bits=10)
        offset_corrector_0 = offset_corrector(clearn, dac_clock, correct_i,
                                              correct_q, gain_corrected,
                                              corrected)
        duc_chain = duc_chain + (offset_corrector_0, )

    else:
        corrected = rf_out

    offset = Signature("binary_offset", False, bits=10)
    offseter = binary_offseter(clearn, dac_clock, corrected, offset)
    duc_chain = duc_chain + (offseter, )

    interleaver_0 = interleaver(clearn, dac_clock, dac2x_clock, offset, dac_en,
                                dac_data, dac_last)
    duc_chain = duc_chain + (interleaver_0, )

    # DIGITAL DOWN CONVERTER
    rx_offset_corrected = Signature("rx_offset_corrected", True, bits=10)
    rx_offset_corrector = offset_corrector(clearn, dac_clock, rx_correct_i,
                                           rx_correct_q, adc_sample,
                                           rx_offset_corrected)
    ddc_chain = (rx_offset_corrector, )

    downsampled = Signature("downsampled", True, bits=10)
    downsampled_i = downsampled.i
    downsampled_q = downsampled.q
    downsampled_valid = downsampled.valid
    downsampler_0 = downsampler(clearn, dac_clock, rx_offset_corrected,
                                downsampled, decim)
    ddc_chain = ddc_chain + (downsampler_0, )

    @always_seq(dac_clock.posedge, reset=clearn)
    def synchronizer():
        sync_txen.next = system_txen
        txen.next = sync_txen
        sync_txstop.next = system_txstop
        txstop.next = sync_txstop
        sync_ddsen.next = system_ddsen
        ddsen.next = sync_ddsen
        sync_filteren.next = system_filteren
        filteren.next = sync_filteren
        sync_interp.next = system_interp
        interp.next = sync_interp
        sync_shift.next = system_shift
        shift.next = sync_shift
        sync_firen.next = system_firen
        firen.next = sync_firen
        sync_fir_bank1.next = system_fir_bank1
        fir_bank1.next = sync_fir_bank1
        sync_fir_bank0.next = system_fir_bank0
        fir_bank0.next = sync_fir_bank0
        sync_fir_N.next = system_fir_N
        fir_N.next = sync_fir_N
        sync_fcw.next = system_fcw
        fcw.next = sync_fcw
        sync_correct_i.next = system_correct_i
        correct_i.next = sync_correct_i
        sync_correct_q.next = system_correct_q
        correct_q.next = sync_correct_q
        sync_gain_i.next = system_gain_i
        gain_i.next = sync_gain_i
        sync_gain_q.next = system_gain_q
        gain_q.next = sync_gain_q
        sync_rx_correct_i.next = system_rx_correct_i
        rx_correct_i.next = sync_rx_correct_i
        sync_rx_correct_q.next = system_rx_correct_q
        rx_correct_q.next = sync_rx_correct_q

    interp_counter = Signal(intbv(0)[32:])
    done = Signal(bool(0))

    decim_counter = Signal(intbv(0)[32:])
    rx_done = Signal(bool(0))

    @always_seq(dac_clock.posedge, reset=clearn)
    def consumer():
        if txen:
            if interp_counter == 0:
                interp_counter.next = interp - 1
                if fifo_empty:
                    if txstop:
                        done.next = True
                        fifo_re.next = False
                    else:
                        underrun.next = underrun + 1
                        done.next = False
                        fifo_re.next = False
                else:
                    done.next = False
                    fifo_re.next = True
            else:
                interp_counter.next = interp_counter - 1
                fifo_re.next = False

    @always_seq(dac_clock.posedge, reset=clearn)
    def producer():
        if rxen and downsampled_valid:
            if rx_fifo_full:
                if rxstop:
                    rx_done.next = True
                    rx_fifo_we.next = False
                else:
                    rx_overrun.next = rx_overrun + 1
                    rx_done.next = False
                    rx_fifo_we.next = False
            else:
                rx_done.next = False
                rx_fifo_we.next = True
        else:
            rx_done.next = False
            rx_fifo_we.next = False

    @always_seq(dac_clock.posedge, reset=clearn)
    def sampler():
        if txen:
            if done:
                sample_i.next = 0
                sample_q.next = 0
                sample_valid.next = True
                sample_last.next = True
            elif fifo_dvld:
                sample_i.next = fifo_rdata[16:].signed()
                sample_q.next = fifo_rdata[32:16].signed()
                sample_valid.next = True
                sample_last.next = False
            else:
                sample_i.next = 0
                sample_q.next = 0
                sample_valid.next = False
                sample_last.next = False
        else:
            sample_i.next = 0
            sample_q.next = 0
            sample_valid.next = False
            sample_last.next = False

        if rxen and downsampled_valid:
            rx_fifo_wdata.next = concat(downsampled_q[9], downsampled_q[9],
                                        downsampled_q[9], downsampled_q[9],
                                        downsampled_q[9], downsampled_q[9],
                                        downsampled_q[10:], downsampled_i[9],
                                        downsampled_i[9], downsampled_i[9],
                                        downsampled_i[9], downsampled_i[9],
                                        downsampled_i[9], downsampled_i[10:])
        else:
            rx_fifo_wdata.next = 0

    return (
        synchronizer,
        consumer,
        producer,
        sampler,
    ) + duc_chain + ddc_chain
Esempio n. 2
0
def cic_decim(clearn, clock,
        in_sign,
        out_sign,
        decim,
        #shift,
        cic_order=4, cic_delay=2, **kwargs):
    """A cic decimating filter with given order and delay.

    :param clearn: Reset the filter.
    :param clock: The clock.
    :param in_sign: The input signature.
    :param out_sign: The output signature.
    :param decim: The decimation of the cic filter.
    :param shift: How much to shift the result.
    :param cic_order: The order of the CIC filter.
    :param cic_delay: The delay of the CIC comb elements.
    :returns: A synthesizable MyHDL instance.
    """
    in_valid = in_sign.valid
    in_i = in_sign.i
    in_q = in_sign.q
    in_last = in_sign.last
    out_last = out_sign.last
    out_valid = out_sign.valid
    out_i = out_sign.i
    out_q = out_sign.q
    rates = kwargs.get('rates', [decim])
    max_rate = max(rates)

    accumed = [Signature('accumed_%d' % i, True, bits=cic_decim_register_width(
            len(in_i), len(out_i), max_rate, cic_order, cic_delay,
            i)) for i in range(1, cic_order + 1)]
    print 'accumed', accumed
    combed = [Signature('combed_%d' % i, True, bits=cic_decim_register_width(
            len(in_i), len(out_i), max_rate, cic_order, cic_delay,
            cic_order + i)) for i in range(1, cic_order + 1)]
    print 'combed', combed

    accums = []
    for n in range(cic_order):
        if n == 0:
            i = in_sign
        else:
            i = accumed[n - 1]

        o = accumed[n]

        print 'accum in=%d, out=%d' % (len(i.q), len(o.q))
        accums.append(accumulator(clearn, clock, i, o, n))  # TODO truncate

    decimated = accumed[cic_order - 1].copy('decimated')
    decimator_0 = downsampler(clearn, clock,
        accumed[cic_order - 1], decimated,
        decim)

    combs = []
    for n in range(cic_order):
        if n == 0:
            i = decimated
        else:
            i = combed[n - 1]

        o = combed[n]

        print 'comb in=%d, out=%d' % (len(i.q), len(o.q))
        combs.append(comb(clearn, clock, cic_delay, i, o))  # TODO truncate
    
    # TODO: does this need a shifter?  yeah.
    truncator_0 = truncator(clearn, clock,
        combed[cic_order - 1], out_sign)

    instances = accums, decimator_0, combs, truncator_0

    if kwargs.get('sim', None):
        sim = kwargs['sim']
        sim.record(in_sign)
        [sim.record(a) for a in accumed]
        sim.record(decimated)
        [sim.record(c) for c in combed]
        sim.record(out_sign)

    return instances
Esempio n. 3
0
def duc(clearn, dac_clock, dac2x_clock,
        loopen, loopback,
        fifo_empty, fifo_re, fifo_dvld, fifo_rdata, fifo_underflow,
        system_txen, system_txstop,
        system_ddsen, system_filteren,
        system_interp, system_shift,
        system_fcw,
        system_correct_i, system_correct_q,
        system_gain_i, system_gain_q,
        underrun, sample,
        dac_en, dac_data, dac_last,

        rx_fifo_full, rx_fifo_we, rx_fifo_wdata,
        rxen, rxstop, rxfilteren,
        decim, system_rx_correct_i, system_rx_correct_q,
        rx_overrun, rx_sample,
        adc_idata, adc_qdata, adc_last,

        fir_coeff_ram_addr,
        fir_coeff_ram_din0,
        fir_coeff_ram_din1,
        fir_coeff_ram_blk,
        fir_coeff_ram_wen,
        fir_coeff_ram_dout0,
        fir_coeff_ram_dout1,
        fir_delay_line_i_ram_addr,
        fir_delay_line_i_ram_din,
        fir_delay_line_i_ram_blk,
        fir_delay_line_i_ram_wen,
        fir_delay_line_i_ram_dout,
        fir_delay_line_q_ram_addr,
        fir_delay_line_q_ram_din,
        fir_delay_line_q_ram_blk,
        fir_delay_line_q_ram_wen,
        fir_delay_line_q_ram_dout,
        system_firen, system_fir_bank1, system_fir_bank0, system_fir_N,
        **kwargs):
    """The Digital Up Converter.    

    :param clearn: Reset signal, completely resets the dsp chain.
    :param dac_clock: The sampling clock.
    :param dac2x_clock: Twice the sampling clock.
    :param loopen: Enable the loopback device.
    :param loopback: The loopback signature to the digital down converter.
    :param fifo_empty: Input signal that the fifo is empty.
    :param fifo_re: Output signal to enable a sample read.
    :param fifo_dvld: Input signal that FIFO data is valid.
    :param fifo_rdata: Input sample data.
    :param fifo_underflow: Input signal that fifo underflowed.
    :param system_txen: Enable transmit.
    :param system_txstop: Stop the transmitter.
    :param system_ddsen: Enable the DDS.
    :param system_filteren: Enable the CIC filter.
    :param system_interp: Interpolation rate.
    :param system_fcw: Set the frequency control word of the DDS.
    :param system_correct_i: Set the i-Channel AQM DC Offset Correction.
    :param system_correct_q: Set the q-Channel AQM DC Offset Correction.
    :param system_gain_i: Set the i-channel AQM gain correction.
    :param system_gain_q: Set the q-channel AQM gain correction.
    :param underrun: Output of number of underruns to RFE.
    :param sample: The sample.
    :param dac_en: Enable DAC on valid data signal.
    :param dac_data: The interleaved DAC data.
    :param dac_last: The last sample going out on the DAC, stops the transmit.
    :returns: A MyHDL synthesizable module.
    """

    dspsim = kwargs.get('dspsim', None)

    # DIGIAL UP CONVERTER
    interp_default = kwargs.get('interp', 1)

    sync_txen = Signal(bool(0))
    txen = Signal(bool(0))
    sync_txstop = Signal(bool(0))
    txstop = Signal(bool(0))
    sync_ddsen = Signal(bool(0))
    ddsen = Signal(bool(0))
    sync_filteren = Signal(bool(0))
    filteren = Signal(bool(0))
    sync_interp = Signal(intbv(interp_default)[len(system_interp):])
    interp = Signal(intbv(interp_default)[len(system_interp):])
    sync_shift = Signal(intbv(0)[len(system_shift):])
    shift = Signal(intbv(0)[len(system_shift):])
    sync_firen = Signal(bool(0))
    firen = Signal(bool(0))
    sync_fir_bank0 = Signal(bool(0))
    fir_bank0 = Signal(bool(0))
    sync_fir_bank1 = Signal(bool(0))
    fir_bank1 = Signal(bool(0))
    sync_fir_N = Signal(intbv(0, min=system_fir_N.min, max=system_fir_N.max))
    fir_N = Signal(intbv(0, min=system_fir_N.min, max=system_fir_N.max))
    sync_fcw = Signal(intbv(0)[len(system_fcw):])
    fcw = Signal(intbv(0)[len(system_fcw):])
    sync_correct_i = Signal(intbv(0)[len(system_correct_i):])
    correct_i = Signal(intbv(0)[len(system_correct_i):])
    sync_correct_q = Signal(intbv(0)[len(system_correct_q):])
    correct_q = Signal(intbv(0)[len(system_correct_q):])
    sync_gain_i = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    gain_i = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    sync_gain_q = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    gain_q = Signal(intbv(int(1.0 * 2**9 + .5))[10:])
    sync_rx_correct_i = Signal(intbv(0)[len(system_rx_correct_i):])
    rx_correct_i = Signal(intbv(0)[len(system_rx_correct_i):])
    sync_rx_correct_q = Signal(intbv(0)[len(system_rx_correct_q):])
    rx_correct_q = Signal(intbv(0)[len(system_rx_correct_q):])

    sample_valid = sample.valid
    sample_last = sample.last
    sample_i = sample.i
    sample_q = sample.q

    rx_sample_valid = rx_sample.valid
    rx_sample_last = rx_sample.last
    rx_sample_i = rx_sample.i
    rx_sample_q = rx_sample.q

    adc_sample = Signature("adc", True, bits=10,
        valid=rxen,
        last=adc_last,
        i=adc_idata,
        q=adc_qdata)

    truncated_1 = Signature("truncated1", True, bits=9)
    truncator_1 = truncator(clearn, dac_clock, sample, truncated_1)
    duc_chain = (truncator_1, )

    if kwargs.get('dds_enable', True):
        if_out = Signature("if_out", True, bits=9)
        dds_args = clearn, dac_clock, ddsen, truncated_1, if_out, fcw
        dds = DDS(*dds_args, num_samples=DDS_NUM_SAMPLES)
        duc_chain = duc_chain + (dds, )
    else:
        if_out = truncated_1

    if kwargs.get('fir_enable', True):
        filtered = Signature("filtered", True, bits=9)
        fir_0 = FIR(clearn, dac_clock, if_out, filtered,
                    fir_coeff_ram_addr,
                    fir_coeff_ram_din0,
                    fir_coeff_ram_din1,
                    fir_coeff_ram_blk,
                    fir_coeff_ram_wen,
                    fir_coeff_ram_dout0,
                    fir_coeff_ram_dout1,
                    fir_delay_line_i_ram_addr,
                    fir_delay_line_i_ram_din,
                    fir_delay_line_i_ram_blk,
                    fir_delay_line_i_ram_wen,
                    fir_delay_line_i_ram_dout,
                    fir_delay_line_q_ram_addr,
                    fir_delay_line_q_ram_din,
                    fir_delay_line_q_ram_blk,
                    fir_delay_line_q_ram_wen,
                    fir_delay_line_q_ram_dout,
                    firen, fir_bank1, fir_bank0, fir_N)
        duc_chain = duc_chain + (fir_0, )
    else:
        filtered = if_out

    upsampled = Signature("upsampled", True, bits=9)
    upsampler_0 = upsampler(clearn, dac_clock, filtered, upsampled, interp)
    duc_chain = duc_chain + (upsampler_0, )

    if kwargs.get('cic_enable', True):
        rate_changed = Signature("rate_changed", True, bits=10)
        cic_0 = cic(clearn, dac_clock, filtered, rate_changed,
                interp,
                shift,
                cic_order=kwargs.get('cic_order', 4),
                cic_delay=kwargs.get('cic_delay', 1),
                sim=dspsim)
        duc_chain = duc_chain + (cic_0, )

        processed = Signature("processed", True, bits=10)
        processed_mux = iqmux(clearn, dac_clock,
                filteren,
                upsampled, rate_changed, processed)
        duc_chain = duc_chain + (processed_mux, )
    else:
        processed = upsampled

    rf_out = processed

    tx_loopback = pass_through_with_enable(clearn, dac_clock,
        rf_out, loopback, loopen)
    duc_chain = duc_chain + (tx_loopback, )

    if kwargs.get('conditioning_enable', True):
        gain_corrected = Signature("gain_corrected", True, bits=10)
        gain_corrector_0 = gain_corrector(clearn, dac_clock,
                gain_i, gain_q,
                rf_out, gain_corrected)
        duc_chain = duc_chain + (gain_corrector_0, )

        corrected = Signature("offset_corrected", True, bits=10)
        offset_corrector_0 = offset_corrector(clearn, dac_clock,
                correct_i, correct_q,
                gain_corrected, corrected)
        duc_chain = duc_chain + (offset_corrector_0, )
        
    else:
        corrected = rf_out

    offset = Signature("binary_offset", False, bits=10)
    offseter = binary_offseter(clearn, dac_clock,
            corrected, offset)
    duc_chain = duc_chain + (offseter, )

    interleaver_0 = interleaver(clearn, dac_clock, dac2x_clock,
            offset, 
            dac_en, dac_data, dac_last)
    duc_chain = duc_chain + (interleaver_0, )

    # DIGITAL DOWN CONVERTER
    rx_offset_corrected = Signature("rx_offset_corrected", True, bits=10)
    rx_offset_corrector = offset_corrector(clearn, dac_clock,
                rx_correct_i, rx_correct_q,
                adc_sample, rx_offset_corrected)
    ddc_chain = (rx_offset_corrector, )

    downsampled = Signature("downsampled", True, bits=10)
    downsampled_i = downsampled.i
    downsampled_q = downsampled.q
    downsampled_valid = downsampled.valid
    downsampler_0 = downsampler(clearn, dac_clock, rx_offset_corrected,
            downsampled, decim)
    ddc_chain = ddc_chain + (downsampler_0, )

    @always_seq(dac_clock.posedge, reset=clearn)
    def synchronizer():
        sync_txen.next = system_txen
        txen.next = sync_txen
        sync_txstop.next = system_txstop
        txstop.next = sync_txstop
        sync_ddsen.next = system_ddsen
        ddsen.next = sync_ddsen
        sync_filteren.next = system_filteren
        filteren.next = sync_filteren
        sync_interp.next = system_interp
        interp.next = sync_interp
        sync_shift.next = system_shift
        shift.next = sync_shift
        sync_firen.next = system_firen
        firen.next = sync_firen
        sync_fir_bank1.next = system_fir_bank1
        fir_bank1.next = sync_fir_bank1
        sync_fir_bank0.next = system_fir_bank0
        fir_bank0.next = sync_fir_bank0
        sync_fir_N.next = system_fir_N
        fir_N.next = sync_fir_N
        sync_fcw.next = system_fcw
        fcw.next = sync_fcw
        sync_correct_i.next = system_correct_i
        correct_i.next = sync_correct_i
        sync_correct_q.next = system_correct_q
        correct_q.next = sync_correct_q
        sync_gain_i.next = system_gain_i
        gain_i.next = sync_gain_i
        sync_gain_q.next = system_gain_q
        gain_q.next = sync_gain_q
        sync_rx_correct_i.next = system_rx_correct_i
        rx_correct_i.next = sync_rx_correct_i
        sync_rx_correct_q.next = system_rx_correct_q
        rx_correct_q.next = sync_rx_correct_q

    interp_counter = Signal(intbv(0)[32:])
    done = Signal(bool(0))

    decim_counter = Signal(intbv(0)[32:])
    rx_done = Signal(bool(0))

    @always_seq(dac_clock.posedge, reset=clearn)
    def consumer():
        if txen:
            if interp_counter == 0:
                interp_counter.next = interp - 1
                if fifo_empty:
                    if txstop:
                        done.next = True
                        fifo_re.next = False
                    else:
                        underrun.next = underrun + 1
                        done.next = False
                        fifo_re.next = False
                else:
                    done.next = False
                    fifo_re.next = True
            else:
                interp_counter.next = interp_counter - 1
                fifo_re.next = False

    @always_seq(dac_clock.posedge, reset=clearn)
    def producer():
        if rxen and downsampled_valid:
            if rx_fifo_full:
                if rxstop:
                    rx_done.next = True
                    rx_fifo_we.next = False
                else:
                    rx_overrun.next = rx_overrun + 1
                    rx_done.next = False
                    rx_fifo_we.next = False
            else:
                rx_done.next = False
                rx_fifo_we.next = True
        else:
            rx_done.next = False
            rx_fifo_we.next = False

    @always_seq(dac_clock.posedge, reset=clearn)
    def sampler():
        if txen:
            if done:
                sample_i.next = 0
                sample_q.next = 0
                sample_valid.next = True
                sample_last.next = True
            elif fifo_dvld:
                sample_i.next = fifo_rdata[16:].signed()
                sample_q.next = fifo_rdata[32:16].signed()
                sample_valid.next = True
                sample_last.next = False
            else:
                sample_i.next = 0
                sample_q.next = 0
                sample_valid.next = False
                sample_last.next = False
        else:
            sample_i.next = 0
            sample_q.next = 0
            sample_valid.next = False
            sample_last.next = False

        if rxen and downsampled_valid:
            rx_fifo_wdata.next = concat(
                downsampled_q[9], downsampled_q[9],
                downsampled_q[9], downsampled_q[9], downsampled_q[9],
                downsampled_q[9], downsampled_q[10:],
                downsampled_i[9], downsampled_i[9],
                downsampled_i[9], downsampled_i[9], downsampled_i[9],
                downsampled_i[9], downsampled_i[10:])
        else:
            rx_fifo_wdata.next = 0
    
    return (synchronizer, consumer, producer, sampler, ) + duc_chain + ddc_chain