def make_expgen_ios(): clk = Signal(False) reset = Signal(False) target = unsigned_bus(N + FRACTION_BITS + 2) latch_dq = Signal(False) slope = unsigned_bus(4) qi = unsigned_bus(N) return (clk, reset, target, latch_dq, slope, qi)
def make_wavgen_ios(): clk = Signal(False) reset = Signal(False) select = unsigned_bus(2) threshold = unsigned_bus(N) delta_phase = unsigned_bus(PHASEWIDTH) _output = signed_bus(N) return (clk, reset, select, threshold, delta_phase, _output)
def make_adsr_ios(): clk = Signal(False) keydown = Signal(False) attack = unsigned_bus(4) decay = unsigned_bus(4) sustain = unsigned_bus(4) release = unsigned_bus(4) _out = unsigned_bus(N) return (clk, keydown, attack, sustain, decay, release, _out)
def delta_sigma_dac(fastclk, clk, reset, input_data, dac_bit): interp_result = signed_bus(N) interp_result_unsigned = unsigned_bus(N) # the input of the Xilinx multiplier is an 18-bit factor vc_estimate = unsigned_bus(16) # the output of the Xilinx multiplier is a 36-bit product sum_of_products = unsigned_bus(32) dac_bit_internal = Signal(False) @always_comb def drive_dac_bit(): dac_bit.next = dac_bit_internal @always(fastclk.posedge, reset.posedge) def do_stuff(): # sum_of_products is the next value for vc_estimate, with lots of fraction # bits. vc_estimate already has fraction bits beyond N. All these fraction # bits are helpful in keeping out audible artifacts. if reset: dac_bit_internal.next = 0 vc_estimate.next = 1 << 15 else: dac_bit_internal.next = interp_result_unsigned > ( sum_of_products >> (32 - N)) vc_estimate.next = sum_of_products >> 16 @always_comb def multiply(): if dac_bit_internal: if A + (B * vc_estimate) >= (1 << 32): sum_of_products.next = (1 << 32) - 1 else: sum_of_products.next = A + (B * vc_estimate) else: sum_of_products.next = B * vc_estimate things = [ # Interpolation is a huge help with anti-aliasing. interpolator(fastclk, clk, reset, input_data, interp_result), drive_dac_bit, do_stuff, multiply, signed_to_unsigned(N, interp_result, interp_result_unsigned) ] return things
def delta_sigma_dac(fastclk, clk, reset, input_data, dac_bit): interp_result = signed_bus(N) interp_result_unsigned = unsigned_bus(N) # the input of the Xilinx multiplier is an 18-bit factor vc_estimate = unsigned_bus(16) # the output of the Xilinx multiplier is a 36-bit product sum_of_products = unsigned_bus(32) dac_bit_internal = Signal(False) @always_comb def drive_dac_bit(): dac_bit.next = dac_bit_internal @always(fastclk.posedge, reset.posedge) def do_stuff(): # sum_of_products is the next value for vc_estimate, with lots of fraction # bits. vc_estimate already has fraction bits beyond N. All these fraction # bits are helpful in keeping out audible artifacts. if reset: dac_bit_internal.next = 0 vc_estimate.next = 1 << 15 else: dac_bit_internal.next = interp_result_unsigned > (sum_of_products >> (32 - N)) vc_estimate.next = sum_of_products >> 16 @always_comb def multiply(): if dac_bit_internal: if A + (B * vc_estimate) >= (1 << 32): sum_of_products.next = (1 << 32) - 1 else: sum_of_products.next = A + (B * vc_estimate) else: sum_of_products.next = B * vc_estimate things = [ # Interpolation is a huge help with anti-aliasing. interpolator(fastclk, clk, reset, input_data, interp_result), drive_dac_bit, do_stuff, multiply, signed_to_unsigned(N, interp_result, interp_result_unsigned) ] return things
def make_fpga_ios(): fastclk = Signal(False) reset = Signal(False) param_data = unsigned_bus(4) param_clk = Signal(False) audio_req = Signal(False) audio_ack = Signal(False) dac_bit = Signal(True) return (fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit)
def exponential_generator(clk, reset, target, latch_dq, slope, qi): """ ATTACK: target = 2 << (N + FRACTION_BITS) DECAY: target = S << (N + FRACTION_BITS - 4) ^ the idea here is to left-shift S so its MSB lines up RELEASE: target = 0 """ q = unsigned_bus(N + FRACTION_BITS + 2) dq = unsigned_bus(N + FRACTION_BITS + 2) sign_bit = Signal(False) @always(clk.posedge) def compute_dq(): if latch_dq and not reset: x = target - q if target >= q: sign_bit.next = False else: sign_bit.next = True x = -x if slope & 1: # divide by sqrt(2), approximately x = (x >> 1) + (x >> 3) + (x >> 4) dq.next = x >> (LCOUNT_BITS + 3 + (slope >> 1)) @always(clk.posedge) def update_q(): if reset: q.next = 0 elif sign_bit: q.next = q - dq else: q.next = q + dq @always_comb def drive_qi_qf(): if (q >> FRACTION_BITS) > MASK: qi.next = MASK else: qi.next = q >> FRACTION_BITS return (compute_dq, update_q, drive_qi_qf)
def lcounter(clk, lzero): lbits = unsigned_bus(LCOUNT_BITS) @always_comb def _output(): lzero.next = (lbits == 0) @always(clk.posedge) def count(): lbits.next = (lbits + 1) & ((1 << LCOUNT_BITS) - 1) return (_output, count)
def adsr(clk, keydown, attack, sustain, decay, release, _out): reset = Signal(False) keydown1 = Signal(False) keydown2 = Signal(False) lzero = Signal(False) threshold = Signal(False) state = unsigned_bus(2) target = unsigned_bus(N + FRACTION_BITS + 2) latch_dq = Signal(False) slope = unsigned_bus(4) qi = unsigned_bus(N) @always_comb def combinatorial(): latch_dq.next = (keydown1 and not keydown2) or (keydown2 and not keydown1) or lzero threshold.next = (qi == MASK) _out.next = qi if state == ATTACK: slope.next = attack elif state == DECAY: slope.next = decay else: slope.next = release @always(clk.posedge) def synchronous(): keydown1.next = keydown keydown2.next = keydown1 reset.next = 0 sm = state_machine(clk, keydown, threshold, state) eg = exponential_generator(clk, reset, target, latch_dq, slope, qi) et = exponential_target(state, sustain, target) lc = lcounter(clk, lzero) return (sm, eg, et, lc, synchronous, combinatorial)
def vca(clk, input_signed, input_unsigned, output_signed): a = signed_bus(18) b = unsigned_bus(18) ab = signed_bus(36) @always(clk.posedge) def get_inputs(): a.next = input_signed b.next = input_unsigned @always_comb def multiply(): ab.next = a * b @always_comb def drive_output(): output_signed.next = (ab >> N) return (get_inputs, multiply, drive_output)
def state_machine(clk, keydown, threshold, state): _state = unsigned_bus(2) @always_comb def drive_outputs(): state.next = _state @always(clk.posedge) def transitions(): if not keydown: _state.next = RELEASE elif _state > RELEASE: _state.next = RELEASE elif _state == RELEASE and keydown: _state.next = ATTACK elif _state == ATTACK and threshold: _state.next = DECAY else: _state.next = _state return (drive_outputs, transitions)
def make_ios(): clk = Signal(False) input_signed = signed_bus(N) input_unsigned = unsigned_bus(N) output_signed = signed_bus(N) return (clk, input_signed, input_unsigned, output_signed)
def waveform_generator(clk, reset, select, threshold, delta_phase, _output): NOISEWIDTH16 = 16 # depends on polynomial NOISEWIDTH13 = 13 HALFPHASE = 1 << (PHASEWIDTH - 1) QUARTERPHASE = 1 << (PHASEWIDTH - 2) THREEQUARTERPHASE = HALFPHASE + QUARTERPHASE TRIANGLESHIFT = (PHASEWIDTH - N) - 1 RAMPSHIFT = PHASEWIDTH - N phase_counter = unsigned_bus(PHASEWIDTH) noise_register_16 = unsigned_bus(NOISEWIDTH16) noise_register_13 = unsigned_bus(NOISEWIDTH13) @always(clk.posedge, reset.posedge) def waveforms(): if reset: noise_register_16.next = 123 noise_register_13.next = 1787 phase_counter.next = 0 _output.next = 0 else: if noise_register_16 == 0: noise_register_16.next = 123 elif (noise_register_16 ^ (noise_register_16 >> 2) ^ (noise_register_16 >> 3) ^ (noise_register_16 >> 5)) & 1: noise_register_16.next = (1 << 15) + (noise_register_16 >> 1) else: noise_register_16.next = (noise_register_16 >> 1) if noise_register_13 == 0: noise_register_13.next = 1787 elif (noise_register_13 ^ (noise_register_13 >> 1) ^ (noise_register_13 >> 2) ^ (noise_register_13 >> 5)) & 1: noise_register_13.next = (1 << 12) + (noise_register_13 >> 1) else: noise_register_13.next = (noise_register_13 >> 1) if phase_counter + delta_phase >= (1 << PHASEWIDTH): phase_counter.next = phase_counter + delta_phase - ( 1 << PHASEWIDTH) else: phase_counter.next = phase_counter + delta_phase if select == RAMP: _output.next = (phase_counter - HALFPHASE) >> RAMPSHIFT elif select == TRIANGLE: if phase_counter < HALFPHASE: _output.next = (phase_counter - QUARTERPHASE) >> TRIANGLESHIFT else: _output.next = \ (THREEQUARTERPHASE - phase_counter) >> TRIANGLESHIFT elif select == SQWAVE: if phase_counter > (threshold << (PHASEWIDTH - N)): _output.next = MASK - HALF else: _output.next = -HALF else: # NOISE _output.next = \ ((noise_register_16 ^ noise_register_13) & MASK) - HALF return waveforms
def fpga(fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit): aclk_counter = unsigned_bus(10) clk = Signal(False) # audio rate clock @always(fastclk.posedge, reset.posedge) def drive_audio_clock(): if reset: aclk_counter.next = 0 clk.next = True elif aclk_counter >= 800: aclk_counter.next = 0 clk.next = True else: aclk_counter.next = aclk_counter + 1 clk.next = False ignored, ignored2, select, threshold, delta_phase, wavgen_output = make_wavgen_ios( ) keydown = Signal(False) select = unsigned_bus(2) attack = unsigned_bus(4) decay = unsigned_bus(4) sustain = unsigned_bus(4) _release = unsigned_bus(4) amplitude = unsigned_bus(N) _output = signed_bus(N) # more bits than we really need, 18 bits would give 6.5536 seconds input_driver_count = unsigned_bus(24) @always(clk.posedge, reset.posedge) def drive_inputs(): attack.next = 3 decay.next = 5 sustain.next = 8 _release.next = 0 delta_phase.next = DELTA_PHASE select.next = 1 threshold.next = HALF keydown.next = 0 if reset: keydown.next = 0 input_driver_count.next = 0 elif input_driver_count >= 5 * SECOND: keydown.next = 0 input_driver_count.next = 0 elif input_driver_count < 2 * SECOND: keydown.next = 1 input_driver_count.next = input_driver_count + 1 else: keydown.next = 0 input_driver_count.next = input_driver_count + 1 drivers = [ drive_audio_clock, drive_inputs, waveform_generator(clk, reset, select, threshold, delta_phase, wavgen_output), # adsr(clk, reset, keydown, attack, decay, sustain, _release, amplitude), # vca(fastclk, reset, wavgen_output, amplitude, _output), delta_sigma_dac(fastclk, clk, reset, wavgen_output, dac_bit), ] return drivers
def make_sm_ios(): clk = Signal(False) keydown = Signal(False) threshold = Signal(False) state = unsigned_bus(2) return (clk, keydown, threshold, state)
def fpga(fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit): aclk_counter = unsigned_bus(10) clk = Signal(False) # audio rate clock @always(fastclk.posedge, reset.posedge) def drive_audio_clock(): if reset: aclk_counter.next = 0 clk.next = True elif aclk_counter >= 800: aclk_counter.next = 0 clk.next = True else: aclk_counter.next = aclk_counter + 1 clk.next = False ignored, ignored2, select, threshold, delta_phase, wavgen_output = make_wavgen_ios() keydown = Signal(False) select = unsigned_bus(2) attack = unsigned_bus(4) decay = unsigned_bus(4) sustain = unsigned_bus(4) _release = unsigned_bus(4) amplitude = unsigned_bus(N) _output = signed_bus(N) # more bits than we really need, 18 bits would give 6.5536 seconds input_driver_count = unsigned_bus(24) @always(clk.posedge, reset.posedge) def drive_inputs(): attack.next = 3 decay.next = 5 sustain.next = 8 _release.next = 0 delta_phase.next = DELTA_PHASE select.next = 1 threshold.next = HALF keydown.next = 0 if reset: keydown.next = 0 input_driver_count.next = 0 elif input_driver_count >= 5 * SECOND: keydown.next = 0 input_driver_count.next = 0 elif input_driver_count < 2 * SECOND: keydown.next = 1 input_driver_count.next = input_driver_count + 1 else: keydown.next = 0 input_driver_count.next = input_driver_count + 1 drivers = [ drive_audio_clock, drive_inputs, waveform_generator(clk, reset, select, threshold, delta_phase, wavgen_output), # adsr(clk, reset, keydown, attack, decay, sustain, _release, amplitude), # vca(fastclk, reset, wavgen_output, amplitude, _output), delta_sigma_dac(fastclk, clk, reset, wavgen_output, dac_bit), ] return drivers
def waveform_generator(clk, reset, select, threshold, delta_phase, _output): NOISEWIDTH16 = 16 # depends on polynomial NOISEWIDTH13 = 13 HALFPHASE = 1 << (PHASEWIDTH - 1) QUARTERPHASE = 1 << (PHASEWIDTH - 2) THREEQUARTERPHASE = HALFPHASE + QUARTERPHASE TRIANGLESHIFT = (PHASEWIDTH - N) - 1 RAMPSHIFT = PHASEWIDTH - N phase_counter = unsigned_bus(PHASEWIDTH) noise_register_16 = unsigned_bus(NOISEWIDTH16) noise_register_13 = unsigned_bus(NOISEWIDTH13) @always(clk.posedge, reset.posedge) def waveforms(): if reset: noise_register_16.next = 123 noise_register_13.next = 1787 phase_counter.next = 0 _output.next = 0 else: if noise_register_16 == 0: noise_register_16.next = 123 elif (noise_register_16 ^ (noise_register_16 >> 2) ^ (noise_register_16 >> 3) ^ (noise_register_16 >> 5)) & 1: noise_register_16.next = (1 << 15) + (noise_register_16 >> 1) else: noise_register_16.next = (noise_register_16 >> 1) if noise_register_13 == 0: noise_register_13.next = 1787 elif (noise_register_13 ^ (noise_register_13 >> 1) ^ (noise_register_13 >> 2) ^ (noise_register_13 >> 5)) & 1: noise_register_13.next = (1 << 12) + (noise_register_13 >> 1) else: noise_register_13.next = (noise_register_13 >> 1) if phase_counter + delta_phase >= (1 << PHASEWIDTH): phase_counter.next = phase_counter + delta_phase - (1 << PHASEWIDTH) else: phase_counter.next = phase_counter + delta_phase if select == RAMP: _output.next = (phase_counter - HALFPHASE) >> RAMPSHIFT elif select == TRIANGLE: if phase_counter < HALFPHASE: _output.next = (phase_counter - QUARTERPHASE) >> TRIANGLESHIFT else: _output.next = \ (THREEQUARTERPHASE - phase_counter) >> TRIANGLESHIFT elif select == SQWAVE: if phase_counter > (threshold << (PHASEWIDTH - N)): _output.next = MASK - HALF else: _output.next = -HALF else: # NOISE _output.next = \ ((noise_register_16 ^ noise_register_13) & MASK) - HALF return waveforms