├── README.md
└── fpga-synth
├── README.rst
├── amps_filters.py
├── config.py
├── envgen.py
├── fpga-synth
├── BPC3011-Papilio_Pro-general.ucf
├── fpga-synth.xise
├── fpga_synth.v
└── papilio.ucf
├── fpga.v
├── instrument
├── 555_Monostable.png
├── README.rst
├── body.py
├── musicbox.py
├── musicbox.xise
├── ppro.ucf
├── pslib.py
├── ramp.v
└── simple_body.py
├── output_stage.py
├── param_loading.py
├── synth.py
├── tb_fpga.tf
└── wavegen.py
/README.md:
--------------------------------------------------------------------------------
1 | # Music projects
2 |
3 | These have been sprinkled around different repositories for a few years now.
4 | This is an attempt to bring them together. For now I'm just using git submodules
5 | but at some point I'd like to merge the histories in some not-too-messy way.
6 | Maybe keep the commits in chronological order if possible.
7 |
8 | Meanwhile I'm working on some new stuff, which is not in a submodule.
9 |
--------------------------------------------------------------------------------
/fpga-synth/README.rst:
--------------------------------------------------------------------------------
1 | An FPGA-based synthesizer
2 | =========================
3 |
4 | Back in the 1970s and 80s, I was interested in electronics and music synthesizers, and they were
5 | still a pretty big novelty. By that time, Bob Moog had already identified a collection of analog
6 | modules that could be set up like this to produce a very wide range of interesting, obviously
7 | synthetic musical noises.
8 |
9 | .. image:: http://www.headphone-amplifier.com/pro_light_sound_2008/images/pro_light_and%20_sound_2008_making_musik_analog_synthesizer1_600.jpg
10 |
11 | So a friend and I used to play with this stuff because his father had gotten him started with it,
12 | and then he'd gotten me interested (actually I guess my first impetus was the vinyl album "Switched
13 | On Bach"), and I knew some electronics so that was a welcome addition to his pool of knowledge on
14 | the subject. We had a good time and I built a few electronic musical instruments in college and
15 | immediately after, but then got too busy with my career to pursue it more.
16 |
17 | Fast-forward thirty years, and we have cheap 8- and 32-bit microcontrollers and powerful FPGAs. In
18 | my career as an electrical engineer I'd done some FPGA work, and it has occurred to me that the
19 | kinds of fixed-point arithmetic computations that FPGAs do well are the ones that would do the jobs
20 | of all those analog modules. So my hope/plan is to use a Papilio One or Papilio Pro FPGA board to
21 | make a synthesizer with very few analog parts.
22 |
23 | Getting back into this stuff after 15 years as a software engineer, there has been a bit of a learning
24 | curve. I don't have the resources of a large corporation supporting the FPGA development effort, I
25 | just have what I find online and can purchase mail-order. Sometimes the simulation acts one way and
26 | the chip acts another, so there's a good bit of floundering involved. Some of the early commits in
27 | this repo will be of stuff that just barely works or doesn't work at all, but that's why they call
28 | it a hobby.
29 |
30 | Hacking MyHDL
31 | =============
32 |
33 | Installation on Ubuntu 10.04 (Lucid)
34 | ------------------------------------
35 |
36 | ::
37 |
38 | sudo add-apt-repository ppa:balau82/ppa
39 | sudo apt-get update
40 | sudo apt-get install myhdl gtkwave verilog
41 |
42 | Making sure it works::
43 |
44 | (cd /usr/share/doc/myhdl/examples/rs232; python test_rs232.py)
45 |
46 | Online manual:
47 |
48 | * http://www.myhdl.org/doc/0.6/manual/index.html
49 |
50 | Projects:
51 |
52 | * http://www.myhdl.org/doku.php/projects:intro
53 | * http://www.antfarm.org/blog/aaronf/2008/02/myhdl_a_brief_discussion_2.html
54 | * /usr/share/doc/myhdl/examples
55 |
56 | Installation on OSX 10.8.3 (Mountain Lion)
57 | ------------------------------------------
58 |
59 | Download MyHDL from this website: http://sourceforge.net/projects/myhdl
60 |
61 | Then::
62 |
63 | tar xfz Downloads/myhdl-0.7.tar.gz
64 | cd myhdl-0.7
65 | python setup.py build
66 | sudo python setup.py install
67 |
68 | Unpack the GTKWave zip in the /Applications directory: http://gtkwave.sourceforge.net/gtkwave.zip
69 |
70 | Add this to your .bash_profile::
71 |
72 | export PATH=$PATH:/Applications/gtkwave.app/Contents/Resources/bin
73 |
74 | Add this line to your MyHDL source file::
75 |
76 | Simulation(traceSignals(testBench)).run()
77 |
78 | This will produce a file called testBench.vcd, and now you just type::
79 |
80 | gtkwave testBench.vcd
81 |
82 | Open up the device under test in the upper left, select signals you want to look at, and drag them
83 | over to the waveform display. Right-click on the signal name to choose a data format, including
84 | analog formats that show waveforms.
85 |
86 | The MyBlaze core
87 | ----------------
88 |
89 | MyBlaze is a MyHDL implementation (LGPL) of the GCC-targetable MicroBlaze soft
90 | processor core which runs on Xilinx FPGAs. Some people have run MMU-less Linux
91 | on it, and it can also run FreeRTOS.
92 |
93 | * http://en.wikipedia.org/wiki/MicroBlaze
94 | * https://github.com/wware/myblaze
95 | * http://xilinx.wikidot.com/mb-gnu-tools
96 | * http://xilinx.wikidot.com/microblaze-linux
97 | * Here is a guy in Israel who has done a lot of Microblaze work: http://billauer.co.il/blog/category/fpga/
98 |
--------------------------------------------------------------------------------
/fpga-synth/amps_filters.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import unittest
3 |
4 | from myhdl import Signal, delay, Simulation, always_comb, \
5 | instance, intbv, bin, toVerilog, toVHDL, always, now, traceSignals
6 | from config import (
7 | WHOLE,
8 | HALF,
9 | MASK,
10 | N,
11 | signed_bus,
12 | unsigned_bus,
13 | )
14 |
15 | ########
16 |
17 | def vca(clk, input_signed, input_unsigned, output_signed):
18 | a = signed_bus(18)
19 | b = unsigned_bus(18)
20 | ab = signed_bus(36)
21 |
22 | @always(clk.posedge)
23 | def get_inputs():
24 | a.next = input_signed
25 | b.next = input_unsigned
26 |
27 | @always_comb
28 | def multiply():
29 | ab.next = a * b
30 |
31 | @always_comb
32 | def drive_output():
33 | output_signed.next = (ab >> N)
34 |
35 | return (get_inputs, multiply, drive_output)
36 |
37 | ########
38 |
39 | def make_ios():
40 | clk = Signal(False)
41 | input_signed = signed_bus(N)
42 | input_unsigned = unsigned_bus(N)
43 | output_signed = signed_bus(N)
44 | return (clk, input_signed, input_unsigned, output_signed)
45 |
46 |
47 | class TestVoltageControlledAmplifier(unittest.TestCase):
48 |
49 | def test_vca(self):
50 |
51 | def bench():
52 | clk, input_signed, input_unsigned, output_signed = make_ios()
53 |
54 | v = vca(clk, input_signed, input_unsigned, output_signed)
55 |
56 | @instance
57 | def drive_stuff():
58 | input_signed.next = 0
59 | input_unsigned.next = 0
60 | clk.next = 0
61 | yield delay(1)
62 | clk.next = 1
63 | yield delay(1)
64 | self.assertEqual(0, output_signed)
65 |
66 | input_signed.next = HALF - 1
67 | input_unsigned.next = MASK
68 | clk.next = 0
69 | yield delay(1)
70 | clk.next = 1
71 | yield delay(1)
72 | self.assertEqual(HALF - 2, output_signed)
73 |
74 | input_signed.next = -HALF
75 | input_unsigned.next = MASK
76 | clk.next = 0
77 | yield delay(1)
78 | clk.next = 1
79 | yield delay(1)
80 | self.assertEqual(-HALF, output_signed)
81 |
82 | return (v, drive_stuff)
83 |
84 | tb = bench()
85 | sim = Simulation(tb)
86 | sim.run()
87 |
88 |
89 | if __name__ == '__main__':
90 | if 'hdl' in sys.argv[1:]:
91 | clk, input_signed, input_unsigned, output_signed = make_ios()
92 | toVerilog(vca, clk, input_signed, input_unsigned, output_signed)
93 | else:
94 | suite = unittest.TestLoader().loadTestsFromTestCase(TestVoltageControlledAmplifier)
95 | unittest.TextTestRunner(verbosity=2).run(suite)
96 |
--------------------------------------------------------------------------------
/fpga-synth/config.py:
--------------------------------------------------------------------------------
1 | from myhdl import Signal, delay, always_comb, instance, intbv, bin, always, now
2 |
3 |
4 | ######### General stuff ################
5 |
6 | # Papilio board clocked at 32 MHz, audio rate is 40 kHz
7 | MHZ = 32 * 1000 * 1000
8 | SECOND = AUDIO_RATE = 40 * 1000
9 |
10 | DIVIDER = MHZ / AUDIO_RATE
11 |
12 | N = 14
13 | assert N < 18 # keep multiplier happy
14 |
15 | WHOLE = 1 << N
16 | MASK = WHOLE - 1
17 | HALF = 1 << (N - 1)
18 | QUARTER = 1 << (N - 2)
19 |
20 | PHASEWIDTH = 24
21 |
22 | LOADWIDTH = 4
23 |
24 | (RAMP, TRIANGLE, SQWAVE, NOISE) = range(4)
25 |
26 | def signed_bus(numbits):
27 | min = -(1 << (numbits - 1))
28 | max = 1 << (numbits - 1)
29 | return Signal(intbv(0, min=min, max=max))
30 |
31 | def unsigned_bus(numbits):
32 | return Signal(intbv(0)[numbits:])
33 |
34 | def signed_to_unsigned(nbits, _in, _out):
35 | __out = unsigned_bus(nbits)
36 | @always(_in)
37 | def drive__out():
38 | __out.next = _in + (1 << (nbits - 1))
39 | @always(__out)
40 | def drive_out():
41 | _out.next = __out
42 | return (drive__out, drive_out)
43 |
44 | def unsigned_to_signed(nbits, _in, _out):
45 | __out = signed_bus(nbits)
46 | @always(_in)
47 | def drive__out():
48 | __out.next = _in - (1 << (nbits - 1))
49 | @always(__out)
50 | def drive_out():
51 | _out.next = __out
52 | return (drive__out, drive_out)
53 |
54 |
55 | ############## Simulation stuff ################
56 |
57 | def compute_delta_phase(freq):
58 | ONE_HERTZ = 1. * (1 << PHASEWIDTH) / AUDIO_RATE
59 | return int(round(ONE_HERTZ * freq))
60 |
--------------------------------------------------------------------------------
/fpga-synth/envgen.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import unittest
3 | import math
4 | from myhdl import Signal, delay, Simulation, always_comb, \
5 | instance, intbv, bin, toVerilog, toVHDL, always, now, traceSignals
6 | from config import (
7 | PHASEWIDTH,
8 | N,
9 | MASK,
10 | WHOLE,
11 | HALF,
12 | AUDIO_RATE,
13 | unsigned_bus
14 | )
15 |
16 | FRACTION_BITS = 20
17 | LCOUNT_BITS = 6
18 |
19 |
20 | def lcounter(clk, lzero):
21 | lbits = unsigned_bus(LCOUNT_BITS)
22 |
23 | @always_comb
24 | def _output():
25 | lzero.next = (lbits == 0)
26 |
27 | @always(clk.posedge)
28 | def count():
29 | lbits.next = (lbits + 1) & ((1 << LCOUNT_BITS) - 1)
30 |
31 | return (_output, count)
32 |
33 |
34 | # states
35 | ATTACK, DECAY, RELEASE = range(3)
36 |
37 | # Clock this at the 40 kHz audio rate
38 | def state_machine(clk, keydown, threshold, state):
39 | _state = unsigned_bus(2)
40 |
41 | @always_comb
42 | def drive_outputs():
43 | state.next = _state
44 |
45 | @always(clk.posedge)
46 | def transitions():
47 | if not keydown:
48 | _state.next = RELEASE
49 | elif _state > RELEASE:
50 | _state.next = RELEASE
51 | elif _state == RELEASE and keydown:
52 | _state.next = ATTACK
53 | elif _state == ATTACK and threshold:
54 | _state.next = DECAY
55 | else:
56 | _state.next = _state
57 |
58 | return (drive_outputs, transitions)
59 |
60 |
61 | def make_sm_ios():
62 | clk = Signal(False)
63 | keydown = Signal(False)
64 | threshold = Signal(False)
65 | state = unsigned_bus(2)
66 | return (clk, keydown, threshold, state)
67 |
68 |
69 | def exponential_target(state, sustain, target):
70 |
71 | @always_comb
72 | def choose_target():
73 | if state == ATTACK:
74 | target.next = 2 << (N + FRACTION_BITS)
75 | elif state == DECAY:
76 | # Line up the MSbit of sustain with the MSbit for target
77 | target.next = sustain << (N + FRACTION_BITS - 4)
78 | else: # RELEASE
79 | target.next = 0
80 |
81 | return choose_target
82 |
83 |
84 | def exponential_generator(clk, reset, target, latch_dq, slope, qi):
85 | """
86 | ATTACK: target = 2 << (N + FRACTION_BITS)
87 | DECAY: target = S << (N + FRACTION_BITS - 4)
88 | ^ the idea here is to left-shift S so its MSB lines up
89 | RELEASE: target = 0
90 | """
91 | q = unsigned_bus(N + FRACTION_BITS + 2)
92 | dq = unsigned_bus(N + FRACTION_BITS + 2)
93 | sign_bit = Signal(False)
94 |
95 | @always(clk.posedge)
96 | def compute_dq():
97 | if latch_dq and not reset:
98 | x = target - q
99 | if target >= q:
100 | sign_bit.next = False
101 | else:
102 | sign_bit.next = True
103 | x = -x
104 |
105 | if slope & 1:
106 | # divide by sqrt(2), approximately
107 | x = (x >> 1) + (x >> 3) + (x >> 4)
108 |
109 | dq.next = x >> (LCOUNT_BITS + 3 + (slope >> 1))
110 |
111 | @always(clk.posedge)
112 | def update_q():
113 | if reset:
114 | q.next = 0
115 | elif sign_bit:
116 | q.next = q - dq
117 | else:
118 | q.next = q + dq
119 |
120 | @always_comb
121 | def drive_qi_qf():
122 | if (q >> FRACTION_BITS) > MASK:
123 | qi.next = MASK
124 | else:
125 | qi.next = q >> FRACTION_BITS
126 |
127 | return (compute_dq, update_q, drive_qi_qf)
128 |
129 | def make_expgen_ios():
130 | clk = Signal(False)
131 | reset = Signal(False)
132 | target = unsigned_bus(N + FRACTION_BITS + 2)
133 | latch_dq = Signal(False)
134 | slope = unsigned_bus(4)
135 | qi = unsigned_bus(N)
136 | return (clk, reset, target, latch_dq, slope, qi)
137 |
138 |
139 | def adsr(clk, keydown, attack, sustain, decay, release, _out):
140 | reset = Signal(False)
141 | keydown1 = Signal(False)
142 | keydown2 = Signal(False)
143 | lzero = Signal(False)
144 | threshold = Signal(False)
145 | state = unsigned_bus(2)
146 | target = unsigned_bus(N + FRACTION_BITS + 2)
147 | latch_dq = Signal(False)
148 | slope = unsigned_bus(4)
149 | qi = unsigned_bus(N)
150 |
151 | @always_comb
152 | def combinatorial():
153 | latch_dq.next = (keydown1 and not keydown2) or (keydown2 and not keydown1) or lzero
154 | threshold.next = (qi == MASK)
155 | _out.next = qi
156 | if state == ATTACK:
157 | slope.next = attack
158 | elif state == DECAY:
159 | slope.next = decay
160 | else:
161 | slope.next = release
162 |
163 | @always(clk.posedge)
164 | def synchronous():
165 | keydown1.next = keydown
166 | keydown2.next = keydown1
167 | reset.next = 0
168 |
169 | sm = state_machine(clk, keydown, threshold, state)
170 | eg = exponential_generator(clk, reset, target, latch_dq, slope, qi)
171 | et = exponential_target(state, sustain, target)
172 | lc = lcounter(clk, lzero)
173 |
174 | return (sm, eg, et, lc, synchronous, combinatorial)
175 |
176 | def make_adsr_ios():
177 | clk = Signal(False)
178 | keydown = Signal(False)
179 | attack = unsigned_bus(4)
180 | decay = unsigned_bus(4)
181 | sustain = unsigned_bus(4)
182 | release = unsigned_bus(4)
183 | _out = unsigned_bus(N)
184 | return (clk, keydown, attack, sustain, decay, release, _out)
185 |
186 |
187 | class TestEnvelopeGenerator(unittest.TestCase):
188 |
189 | def test_state_machine(self):
190 |
191 | def bench():
192 | clk, keydown, threshold, state = make_sm_ios()
193 | sm = state_machine(clk, keydown, threshold, state)
194 |
195 | @instance
196 | def drive_stuff():
197 | keydown.next = False
198 | threshold.next = False
199 | clk.next = 0
200 | yield delay(1)
201 | clk.next = 1
202 | yield delay(1)
203 | self.assertEqual(RELEASE, state)
204 |
205 | yield delay(1)
206 | keydown.next = True
207 | yield delay(1)
208 | clk.next = 0
209 | yield delay(1)
210 | clk.next = 1
211 | yield delay(1)
212 | self.assertEqual(ATTACK, state)
213 |
214 | threshold.next = True
215 | yield delay(1)
216 |
217 | clk.next = 0
218 | yield delay(1)
219 | clk.next = 1
220 | yield delay(1)
221 |
222 | self.assertEqual(DECAY, state)
223 | keydown.next = False
224 | yield delay(1)
225 |
226 | clk.next = 0
227 | yield delay(1)
228 | clk.next = 1
229 | yield delay(1)
230 | self.assertEqual(RELEASE, state)
231 |
232 | return (sm, drive_stuff)
233 |
234 | tb = bench()
235 | sim = Simulation(tb)
236 | sim.run()
237 |
238 | def test_exponential_generator(self):
239 |
240 | def bench():
241 | clk, reset, target, latch_dq, slope, qi = make_expgen_ios()
242 | eg = exponential_generator(clk, reset, target, latch_dq, slope, qi)
243 |
244 | @instance
245 | def drive_stuff():
246 | clk.next = 0
247 | reset.next = 1
248 | target.next = 0
249 | latch_dq.next = 0
250 | slope.next = 0
251 | yield delay(1)
252 | clk.next = 1
253 | yield delay(1)
254 | clk.next = 0
255 | yield delay(1)
256 | self.assertEqual(0, qi)
257 | reset.next = 0
258 | yield delay(1)
259 | clk.next = 1
260 | yield delay(1)
261 | clk.next = 0
262 | yield delay(1)
263 | target.next = 1 << N
264 | latch_dq.next = 1
265 | yield delay(1)
266 | clk.next = 1 # this rising edge sets dq
267 | yield delay(1)
268 | clk.next = 0
269 | yield delay(1)
270 | # target should now be a don't-care
271 | latch_dq.next = 0
272 | yield delay(1)
273 | clk.next = 1 # this rising edge increments q
274 | yield delay(1)
275 | clk.next = 0
276 | yield delay(1)
277 | self.assertEqual(1 << (N - LCOUNT_BITS - 3), qi)
278 | clk.next = 1 # this rising edge increments q
279 | yield delay(1)
280 | clk.next = 0
281 | yield delay(1)
282 | self.assertEqual(2 << (N - LCOUNT_BITS - 3), qi)
283 | target.next = 0 # let's try moving down now
284 | latch_dq.next = 1
285 | yield delay(1)
286 | clk.next = 1 # this rising edge sets dq, q keeps going
287 | yield delay(1)
288 | clk.next = 0
289 | yield delay(1)
290 | clk.next = 1 # this rising edge moves q down a little
291 | yield delay(1)
292 | clk.next = 0
293 | yield delay(1)
294 | # q will continue moving up for one more tick, while
295 | q_est = (3 << (N - LCOUNT_BITS - 3)) << FRACTION_BITS
296 | dq_est = q_est >> (LCOUNT_BITS + 3)
297 | q_est -= dq_est
298 | self.assertEqual(q_est >> FRACTION_BITS, qi)
299 |
300 | return (eg, drive_stuff)
301 |
302 | tb = bench()
303 | sim = Simulation(tb)
304 | sim.run()
305 |
306 | def test_lcounter(self):
307 |
308 | def bench():
309 | clk = Signal(False)
310 | lzero = Signal(True)
311 | lc = lcounter(clk, lzero)
312 |
313 | @instance
314 | def drive_stuff():
315 | clk.next = 0
316 | for j in range(2):
317 | for i in range((1 << LCOUNT_BITS) - 1):
318 | yield delay(1)
319 | clk.next = 1
320 | yield delay(1)
321 | clk.next = 0
322 | self.assertEqual(lzero, 0)
323 | yield delay(1)
324 | clk.next = 1
325 | yield delay(1)
326 | clk.next = 0
327 | self.assertEqual(lzero, 1)
328 |
329 | return (lc, drive_stuff)
330 |
331 | tb = bench()
332 | sim = Simulation(tb)
333 | sim.run()
334 |
335 |
336 | def simulate():
337 | clk, keydown, attack, sustain, decay, release, _out = make_adsr_ios()
338 | _adsr = adsr(clk, keydown, attack, sustain, decay, release, _out)
339 |
340 | @instance
341 | def bench():
342 | clk.next = 0
343 | keydown.next = 0
344 | attack.next = 8
345 | sustain.next = 8
346 | decay.next = 2
347 | release.next = 3
348 | for i in range(10000):
349 | yield delay(1)
350 | clk.next = 1
351 | yield delay(1)
352 | clk.next = 0
353 | keydown.next = 1
354 | for i in range(10000):
355 | yield delay(1)
356 | clk.next = 1
357 | yield delay(1)
358 | clk.next = 0
359 | keydown.next = 0
360 | for i in range(10000):
361 | yield delay(1)
362 | clk.next = 1
363 | yield delay(1)
364 | clk.next = 0
365 |
366 | return (bench, _adsr)
367 |
368 |
369 | if __name__ == '__main__':
370 | if 'hdl' in sys.argv[1:]:
371 | clk, keydown, attack, sustain, decay, release, _out = make_adsr_ios()
372 | toVerilog(adsr, clk, keydown, attack, sustain, decay, release, _out)
373 | elif 'sim' in sys.argv[1:]:
374 | Simulation(traceSignals(simulate)).run()
375 | else:
376 | suite = unittest.TestLoader().loadTestsFromTestCase(TestEnvelopeGenerator)
377 | unittest.TextTestRunner(verbosity=2).run(suite)
378 |
--------------------------------------------------------------------------------
/fpga-synth/fpga-synth/BPC3011-Papilio_Pro-general.ucf:
--------------------------------------------------------------------------------
1 | # UCF file for the Papilio Pro board
2 | # Generated by pin_converter, written by Kevin Lindsey
3 | # https://github.com/thelonious/papilio_pins/tree/development/pin_converter
4 |
5 | # Main board wing pin [] to FPGA pin Pxx map
6 | # -------C------- -------B------- -------A-------
7 | # [GND] [C00] P114 [GND] [B00] P99 P100 [A15]
8 | # [2V5] [C01] P115 [2V5] [B01] P97 P98 [A14]
9 | # [3V3] [C02] P116 [3V3] [B02] P92 P93 [A13]
10 | # [5V0] [C03] P117 [5V0] [B03] P87 P88 [A12]
11 | # [C04] P118 [B04] P84 P85 [A11] [5V0]
12 | # [C05] P119 [B05] P82 P83 [A10] [3V3]
13 | # [C06] P120 [B06] P80 P81 [A09] [2V5]
14 | # [C07] P121 [B07] P78 P79 [A08] [GND]
15 | # [GND] [C08] P123 [GND] [B08] P74 P75 [A07]
16 | # [2V5] [C09] P124 [2V5] [B09] P95 P67 [A06]
17 | # [3V3] [C10] P126 [3V3] [B10] P62 P66 [A05]
18 | # [5V0] [C11] P127 [5V0] [B11] P59 P61 [A04]
19 | # [C12] P131 [B12] P57 P58 [A03] [5V0]
20 | # [C13] P132 [B13] P55 P56 [A02] [3V3]
21 | # [C14] P133 [B14] P50 P51 [A01] [2V5]
22 | # [C15] P134 [B15] P47 P48 [A00] [GND]
23 |
24 | ## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
25 | CONFIG PROHIBIT=P144;
26 | CONFIG PROHIBIT=P69;
27 | CONFIG PROHIBIT=P60;
28 |
29 | NET CLK LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
30 | NET RX LOC="P101" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # RX
31 | NET TX LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # TX
32 | NET A(0) LOC="P48" | IOSTANDARD=LVTTL; # A0
33 | NET A(1) LOC="P51" | IOSTANDARD=LVTTL; # A1
34 | NET A(2) LOC="P56" | IOSTANDARD=LVTTL; # A2
35 | NET A(3) LOC="P58" | IOSTANDARD=LVTTL; # A3
36 | NET A(4) LOC="P61" | IOSTANDARD=LVTTL; # A4
37 | NET A(5) LOC="P66" | IOSTANDARD=LVTTL; # A5
38 | NET A(6) LOC="P67" | IOSTANDARD=LVTTL; # A6
39 | NET A(7) LOC="P75" | IOSTANDARD=LVTTL; # A7
40 | NET A(8) LOC="P79" | IOSTANDARD=LVTTL; # A8
41 | NET A(9) LOC="P81" | IOSTANDARD=LVTTL; # A9
42 | NET A(10) LOC="P83" | IOSTANDARD=LVTTL; # A10
43 | NET A(11) LOC="P85" | IOSTANDARD=LVTTL; # A11
44 | NET A(12) LOC="P88" | IOSTANDARD=LVTTL; # A12
45 | NET A(13) LOC="P93" | IOSTANDARD=LVTTL; # A13
46 | NET A(14) LOC="P98" | IOSTANDARD=LVTTL; # A14
47 | NET A(15) LOC="P100" | IOSTANDARD=LVTTL; # A15
48 | NET B(0) LOC="P99" | IOSTANDARD=LVTTL; # B0
49 | NET B(1) LOC="P97" | IOSTANDARD=LVTTL; # B1
50 | NET B(2) LOC="P92" | IOSTANDARD=LVTTL; # B2
51 | NET B(3) LOC="P87" | IOSTANDARD=LVTTL; # B3
52 | NET B(4) LOC="P84" | IOSTANDARD=LVTTL; # B4
53 | NET B(5) LOC="P82" | IOSTANDARD=LVTTL; # B5
54 | NET B(6) LOC="P80" | IOSTANDARD=LVTTL; # B6
55 | NET B(7) LOC="P78" | IOSTANDARD=LVTTL; # B7
56 | NET B(8) LOC="P74" | IOSTANDARD=LVTTL; # B8
57 | NET B(9) LOC="P95" | IOSTANDARD=LVTTL; # B9
58 | NET B(10) LOC="P62" | IOSTANDARD=LVTTL; # B10
59 | NET B(11) LOC="P59" | IOSTANDARD=LVTTL; # B11
60 | NET B(12) LOC="P57" | IOSTANDARD=LVTTL; # B12
61 | NET B(13) LOC="P55" | IOSTANDARD=LVTTL; # B13
62 | NET B(14) LOC="P50" | IOSTANDARD=LVTTL; # B14
63 | NET B(15) LOC="P47" | IOSTANDARD=LVTTL; # B15
64 | NET C(0) LOC="P114" | IOSTANDARD=LVTTL; # C0
65 | NET C(1) LOC="P115" | IOSTANDARD=LVTTL; # C1
66 | NET C(2) LOC="P116" | IOSTANDARD=LVTTL; # C2
67 | NET C(3) LOC="P117" | IOSTANDARD=LVTTL; # C3
68 | NET C(4) LOC="P118" | IOSTANDARD=LVTTL; # C4
69 | NET C(5) LOC="P119" | IOSTANDARD=LVTTL; # C5
70 | NET C(6) LOC="P120" | IOSTANDARD=LVTTL; # C6
71 | NET C(7) LOC="P121" | IOSTANDARD=LVTTL; # C7
72 | NET C(8) LOC="P123" | IOSTANDARD=LVTTL; # C8
73 | NET C(9) LOC="P124" | IOSTANDARD=LVTTL; # C9
74 | NET C(10) LOC="P126" | IOSTANDARD=LVTTL; # C10
75 | NET C(11) LOC="P127" | IOSTANDARD=LVTTL; # C11
76 | NET C(12) LOC="P131" | IOSTANDARD=LVTTL; # C12
77 | NET C(13) LOC="P132" | IOSTANDARD=LVTTL; # C13
78 | NET C(14) LOC="P133" | IOSTANDARD=LVTTL; # C14
79 | NET C(15) LOC="P134" | IOSTANDARD=LVTTL; # C15
80 | NET SDRAM_ADDR(0) LOC="P140" | IOSTANDARD=LVTTL; # SDRAM_ADDR0
81 | NET SDRAM_ADDR(1) LOC="P139" | IOSTANDARD=LVTTL; # SDRAM_ADDR1
82 | NET SDRAM_ADDR(2) LOC="P138" | IOSTANDARD=LVTTL; # SDRAM_ADDR2
83 | NET SDRAM_ADDR(3) LOC="P137" | IOSTANDARD=LVTTL; # SDRAM_ADDR3
84 | NET SDRAM_ADDR(4) LOC="P46" | IOSTANDARD=LVTTL; # SDRAM_ADDR4
85 | NET SDRAM_ADDR(5) LOC="P45" | IOSTANDARD=LVTTL; # SDRAM_ADDR5
86 | NET SDRAM_ADDR(6) LOC="P44" | IOSTANDARD=LVTTL; # SDRAM_ADDR6
87 | NET SDRAM_ADDR(7) LOC="P43" | IOSTANDARD=LVTTL; # SDRAM_ADDR7
88 | NET SDRAM_ADDR(8) LOC="P41" | IOSTANDARD=LVTTL; # SDRAM_ADDR8
89 | NET SDRAM_ADDR(9) LOC="P40" | IOSTANDARD=LVTTL; # SDRAM_ADDR9
90 | NET SDRAM_ADDR(10) LOC="P141" | IOSTANDARD=LVTTL; # SDRAM_ADDR10
91 | NET SDRAM_ADDR(11) LOC="P35" | IOSTANDARD=LVTTL; # SDRAM_ADDR11
92 | NET SDRAM_ADDR(12) LOC="P34" | IOSTANDARD=LVTTL; # SDRAM_ADDR12
93 | NET SDRAM_DATA(0) LOC="P9" | IOSTANDARD=LVTTL; # SDRAM_DATA0
94 | NET SDRAM_DATA(1) LOC="P10" | IOSTANDARD=LVTTL; # SDRAM_DATA1
95 | NET SDRAM_DATA(2) LOC="P11" | IOSTANDARD=LVTTL; # SDRAM_DATA2
96 | NET SDRAM_DATA(3) LOC="P12" | IOSTANDARD=LVTTL; # SDRAM_DATA3
97 | NET SDRAM_DATA(4) LOC="P14" | IOSTANDARD=LVTTL; # SDRAM_DATA4
98 | NET SDRAM_DATA(5) LOC="P15" | IOSTANDARD=LVTTL; # SDRAM_DATA5
99 | NET SDRAM_DATA(6) LOC="P16" | IOSTANDARD=LVTTL; # SDRAM_DATA6
100 | NET SDRAM_DATA(7) LOC="P8" | IOSTANDARD=LVTTL; # SDRAM_DATA7
101 | NET SDRAM_DATA(8) LOC="P21" | IOSTANDARD=LVTTL; # SDRAM_DATA8
102 | NET SDRAM_DATA(9) LOC="P22" | IOSTANDARD=LVTTL; # SDRAM_DATA9
103 | NET SDRAM_DATA(10) LOC="P23" | IOSTANDARD=LVTTL; # SDRAM_DATA10
104 | NET SDRAM_DATA(11) LOC="P24" | IOSTANDARD=LVTTL; # SDRAM_DATA11
105 | NET SDRAM_DATA(12) LOC="P26" | IOSTANDARD=LVTTL; # SDRAM_DATA12
106 | NET SDRAM_DATA(13) LOC="P27" | IOSTANDARD=LVTTL; # SDRAM_DATA13
107 | NET SDRAM_DATA(14) LOC="P29" | IOSTANDARD=LVTTL; # SDRAM_DATA14
108 | NET SDRAM_DATA(15) LOC="P30" | IOSTANDARD=LVTTL; # SDRAM_DATA15
109 | NET SDRAM_DQML LOC="P7" | IOSTANDARD=LVTTL; # SDRAM_DQML
110 | NET SDRAM_DQMH LOC="P17" | IOSTANDARD=LVTTL; # SDRAM_DQMH
111 | NET SDRAM_BA(0) LOC="P143" | IOSTANDARD=LVTTL; # SDRAM_BA0
112 | NET SDRAM_BA(1) LOC="P142" | IOSTANDARD=LVTTL; # SDRAM_BA1
113 | NET SDRAM_nWE LOC="P6" | IOSTANDARD=LVTTL; # SDRAM_nWE
114 | NET SDRAM_nCAS LOC="P5" | IOSTANDARD=LVTTL; # SDRAM_nCAS
115 | NET SDRAM_nRAS LOC="P2" | IOSTANDARD=LVTTL; # SDRAM_nRAS
116 | NET SDRAM_CS LOC="P1" | IOSTANDARD=LVTTL; # SDRAM_CS
117 | NET SDRAM_CLK LOC="P32" | IOSTANDARD=LVTTL; # SDRAM_CLK
118 | NET SDRAM_CKE LOC="P33" | IOSTANDARD=LVTTL; # SDRAM_CKE
119 | NET LED1 LOC="P112" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # LED1
120 | NET JTAG_TMS LOC="P107" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TMS
121 | NET JTAG_TCK LOC="P109" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TCK
122 | NET JTAG_TDI LOC="P110" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDI
123 | NET JTAG_TDO LOC="P106" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDO
124 | NET FLASH_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS
125 | NET FLASH_CK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK
126 | NET FLASH_SI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI
127 | NET FLASH_SO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # FLASH_SO
128 |
--------------------------------------------------------------------------------
/fpga-synth/fpga-synth/fpga-synth.xise:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
--------------------------------------------------------------------------------
/fpga-synth/fpga-synth/fpga_synth.v:
--------------------------------------------------------------------------------
1 | // File: fpga_synth.v
2 | // Generated by MyHDL 0.7
3 | // Date: Tue May 14 22:37:36 2013
4 |
5 |
6 | `timescale 1ns/10ps
7 |
8 | module fpga_synth (
9 | clk,
10 | param_data,
11 | param_clk,
12 | audio_req,
13 | audio_ack,
14 | dac_bit
15 | );
16 |
17 |
18 | input clk;
19 | input [3:0] param_data;
20 | input param_clk;
21 | output audio_req;
22 | wire audio_req;
23 | input audio_ack;
24 | output dac_bit;
25 | reg dac_bit;
26 |
27 | reg audio_tick;
28 | reg [23:0] param_counter;
29 | reg [13:0] _output;
30 | reg [15:0] audio_counter;
31 | reg areq_bit;
32 | reg param_tick;
33 | wire [13:0] dsig_interp_result;
34 | reg [17:0] dsig_vc_estimate;
35 | reg [35:0] dsig_sum_of_products;
36 | reg [22:0] dsig__interp_interp_step;
37 | reg dsig__interp_direction;
38 | reg [22:0] dsig__interp_interp_data;
39 | reg [4:0] dsig__interp_rm_counter;
40 | reg [13:0] dsig__interp_delay_1;
41 | reg dsig__interp_rm_tick;
42 |
43 |
44 |
45 |
46 |
47 | always @(posedge clk) begin: FPGA_SYNTH_AUDIO_SAMPLE_RATE
48 | if ((audio_counter >= (800 - 1))) begin
49 | audio_counter <= 0;
50 | audio_tick <= 1'b1;
51 | end
52 | else begin
53 | audio_counter <= (audio_counter + 1);
54 | audio_tick <= 1'b0;
55 | end
56 | end
57 |
58 |
59 | always @(posedge clk) begin: FPGA_SYNTH_PARAM_SAMPLE_RATE
60 | if ((param_counter >= (32000 - 1))) begin
61 | param_counter <= 0;
62 | param_tick <= 1'b1;
63 | end
64 | else begin
65 | param_counter <= (param_counter + 1);
66 | param_tick <= 1'b0;
67 | end
68 | end
69 |
70 |
71 | always @(posedge param_tick) begin: FPGA_SYNTH_BIG_DUMB_SQUARE_WAVE
72 | areq_bit <= (!areq_bit);
73 | if (areq_bit) begin
74 | areq_bit <= 1'b0;
75 | _output <= 0;
76 | end
77 | else begin
78 | areq_bit <= 1'b1;
79 | _output <= 16383;
80 | end
81 | end
82 |
83 |
84 |
85 | assign audio_req = areq_bit;
86 |
87 |
88 | always @(posedge clk) begin: FPGA_SYNTH_DSIG__INTERP_DO_STUFF
89 | if (((dsig__interp_rm_counter == 0) || (dsig__interp_rm_counter == 3) || (dsig__interp_rm_counter == 6) || (dsig__interp_rm_counter == 9) || (dsig__interp_rm_counter == 11) || (dsig__interp_rm_counter == 14) || (dsig__interp_rm_counter == 17) || (dsig__interp_rm_counter == 20) || (dsig__interp_rm_counter == 23))) begin
90 | dsig__interp_rm_tick <= 1'b0;
91 | end
92 | else begin
93 | dsig__interp_rm_tick <= 1'b1;
94 | end
95 | if ((dsig__interp_rm_counter >= 24)) begin
96 | dsig__interp_rm_counter <= 0;
97 | end
98 | else begin
99 | dsig__interp_rm_counter <= (dsig__interp_rm_counter + 1);
100 | end
101 | if (audio_tick) begin
102 | dsig__interp_delay_1 <= _output;
103 | dsig__interp_interp_data <= (dsig__interp_delay_1 << 9);
104 | if ((_output > dsig__interp_delay_1)) begin
105 | dsig__interp_direction <= 1'b1;
106 | dsig__interp_interp_step <= (_output - dsig__interp_delay_1);
107 | end
108 | else begin
109 | dsig__interp_direction <= 1'b0;
110 | dsig__interp_interp_step <= (dsig__interp_delay_1 - _output);
111 | end
112 | end
113 | else if (dsig__interp_rm_tick) begin
114 | if (dsig__interp_direction) begin
115 | dsig__interp_interp_data <= (dsig__interp_interp_data + dsig__interp_interp_step);
116 | end
117 | else begin
118 | dsig__interp_interp_data <= (dsig__interp_interp_data - dsig__interp_interp_step);
119 | end
120 | end
121 | end
122 |
123 |
124 |
125 | assign dsig_interp_result = (dsig__interp_interp_data >>> 9);
126 |
127 |
128 | always @(posedge clk) begin: FPGA_SYNTH_DSIG_DO_STUFF
129 | dac_bit <= (dsig_interp_result > (dsig_sum_of_products >>> 18));
130 | dsig_vc_estimate <= (dsig_sum_of_products >>> 18);
131 | end
132 |
133 |
134 | always @(dac_bit, dsig_vc_estimate) begin: FPGA_SYNTH_DSIG_MULTIPLY
135 | if (dac_bit) begin
136 | dsig_sum_of_products = ((818 << 14) + (261326 * dsig_vc_estimate));
137 | end
138 | else begin
139 | dsig_sum_of_products = (261326 * dsig_vc_estimate);
140 | end
141 | end
142 |
143 | endmodule
144 |
--------------------------------------------------------------------------------
/fpga-synth/fpga-synth/papilio.ucf:
--------------------------------------------------------------------------------
1 | # UCF file for the Papilio Pro board
2 | # Generated by pin_converter, written by Kevin Lindsey
3 | # https://github.com/thelonious/papilio_pins/tree/development/pin_converter
4 |
5 | # Main board wing pin [] to FPGA pin Pxx map
6 | # -------C------- -------B------- -------A-------
7 | # [GND] [C00] P114 [GND] [B00] P99 P100 [A15]
8 | # [2V5] [C01] P115 [2V5] [B01] P97 P98 [A14]
9 | # [3V3] [C02] P116 [3V3] [B02] P92 P93 [A13]
10 | # [5V0] [C03] P117 [5V0] [B03] P87 P88 [A12]
11 | # [C04] P118 [B04] P84 P85 [A11] [5V0]
12 | # [C05] P119 [B05] P82 P83 [A10] [3V3]
13 | # [C06] P120 [B06] P80 P81 [A09] [2V5]
14 | # [C07] P121 [B07] P78 P79 [A08] [GND]
15 | # [GND] [C08] P123 [GND] [B08] P74 P75 [A07]
16 | # [2V5] [C09] P124 [2V5] [B09] P95 P67 [A06]
17 | # [3V3] [C10] P126 [3V3] [B10] P62 P66 [A05]
18 | # [5V0] [C11] P127 [5V0] [B11] P59 P61 [A04]
19 | # [C12] P131 [B12] P57 P58 [A03] [5V0]
20 | # [C13] P132 [B13] P55 P56 [A02] [3V3]
21 | # [C14] P133 [B14] P50 P51 [A01] [2V5]
22 | # [C15] P134 [B15] P47 P48 [A00] [GND]
23 |
24 | ## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
25 | CONFIG PROHIBIT=P144;
26 | CONFIG PROHIBIT=P69;
27 | CONFIG PROHIBIT=P60;
28 |
29 | # Crystal Clock - use 32MHz onboard oscillator
30 | NET "clk" LOC = "P94" | IOSTANDARD = LVCMOS25 | PERIOD = 31.25ns ;
31 | NET "param_data<0>" LOC = "P48" | PULLUP ;
32 | NET "param_data<1>" LOC = "P51" | PULLUP ;
33 | NET "param_data<2>" LOC = "P56" | PULLUP ;
34 | NET "param_data<3>" LOC = "P58" | PULLUP ;
35 | NET "param_clk" LOC = "P61" | PULLUP ;
36 | NET "audio_req" LOC = "P66" | PULLUP ;
37 | NET "audio_ack" LOC = "P67" | PULLUP ;
38 | NET "dac_bit" LOC = "P75";
39 | # NET "reset" LOC = "P79" | PULLDOWN ;
40 |
41 | #NET CLK LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
42 | #NET RX LOC="P101" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # RX
43 | #NET TX LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # TX
44 | #NET A(0) LOC="P48" | IOSTANDARD=LVTTL; # A0
45 | #NET A(1) LOC="P51" | IOSTANDARD=LVTTL; # A1
46 | #NET A(2) LOC="P56" | IOSTANDARD=LVTTL; # A2
47 | #NET A(3) LOC="P58" | IOSTANDARD=LVTTL; # A3
48 | #NET A(4) LOC="P61" | IOSTANDARD=LVTTL; # A4
49 | #NET A(5) LOC="P66" | IOSTANDARD=LVTTL; # A5
50 | #NET A(6) LOC="P67" | IOSTANDARD=LVTTL; # A6
51 | #NET A(7) LOC="P75" | IOSTANDARD=LVTTL; # A7
52 | #NET A(8) LOC="P79" | IOSTANDARD=LVTTL; # A8
53 | #NET A(9) LOC="P81" | IOSTANDARD=LVTTL; # A9
54 | #NET A(10) LOC="P83" | IOSTANDARD=LVTTL; # A10
55 | #NET A(11) LOC="P85" | IOSTANDARD=LVTTL; # A11
56 | #NET A(12) LOC="P88" | IOSTANDARD=LVTTL; # A12
57 | #NET A(13) LOC="P93" | IOSTANDARD=LVTTL; # A13
58 | #NET A(14) LOC="P98" | IOSTANDARD=LVTTL; # A14
59 | #NET A(15) LOC="P100" | IOSTANDARD=LVTTL; # A15
60 | #NET B(0) LOC="P99" | IOSTANDARD=LVTTL; # B0
61 | #NET B(1) LOC="P97" | IOSTANDARD=LVTTL; # B1
62 | #NET B(2) LOC="P92" | IOSTANDARD=LVTTL; # B2
63 | #NET B(3) LOC="P87" | IOSTANDARD=LVTTL; # B3
64 | #NET B(4) LOC="P84" | IOSTANDARD=LVTTL; # B4
65 | #NET B(5) LOC="P82" | IOSTANDARD=LVTTL; # B5
66 | #NET B(6) LOC="P80" | IOSTANDARD=LVTTL; # B6
67 | #NET B(7) LOC="P78" | IOSTANDARD=LVTTL; # B7
68 | #NET B(8) LOC="P74" | IOSTANDARD=LVTTL; # B8
69 | #NET B(9) LOC="P95" | IOSTANDARD=LVTTL; # B9
70 | #NET B(10) LOC="P62" | IOSTANDARD=LVTTL; # B10
71 | #NET B(11) LOC="P59" | IOSTANDARD=LVTTL; # B11
72 | #NET B(12) LOC="P57" | IOSTANDARD=LVTTL; # B12
73 | #NET B(13) LOC="P55" | IOSTANDARD=LVTTL; # B13
74 | #NET B(14) LOC="P50" | IOSTANDARD=LVTTL; # B14
75 | #NET B(15) LOC="P47" | IOSTANDARD=LVTTL; # B15
76 | #NET C(0) LOC="P114" | IOSTANDARD=LVTTL; # C0
77 | #NET C(1) LOC="P115" | IOSTANDARD=LVTTL; # C1
78 | #NET C(2) LOC="P116" | IOSTANDARD=LVTTL; # C2
79 | #NET C(3) LOC="P117" | IOSTANDARD=LVTTL; # C3
80 | #NET C(4) LOC="P118" | IOSTANDARD=LVTTL; # C4
81 | #NET C(5) LOC="P119" | IOSTANDARD=LVTTL; # C5
82 | #NET C(6) LOC="P120" | IOSTANDARD=LVTTL; # C6
83 | #NET C(7) LOC="P121" | IOSTANDARD=LVTTL; # C7
84 | #NET C(8) LOC="P123" | IOSTANDARD=LVTTL; # C8
85 | #NET C(9) LOC="P124" | IOSTANDARD=LVTTL; # C9
86 | #NET C(10) LOC="P126" | IOSTANDARD=LVTTL; # C10
87 | #NET C(11) LOC="P127" | IOSTANDARD=LVTTL; # C11
88 | #NET C(12) LOC="P131" | IOSTANDARD=LVTTL; # C12
89 | #NET C(13) LOC="P132" | IOSTANDARD=LVTTL; # C13
90 | #NET C(14) LOC="P133" | IOSTANDARD=LVTTL; # C14
91 | #NET C(15) LOC="P134" | IOSTANDARD=LVTTL; # C15
92 | #NET SDRAM_ADDR(0) LOC="P140" | IOSTANDARD=LVTTL; # SDRAM_ADDR0
93 | #NET SDRAM_ADDR(1) LOC="P139" | IOSTANDARD=LVTTL; # SDRAM_ADDR1
94 | #NET SDRAM_ADDR(2) LOC="P138" | IOSTANDARD=LVTTL; # SDRAM_ADDR2
95 | #NET SDRAM_ADDR(3) LOC="P137" | IOSTANDARD=LVTTL; # SDRAM_ADDR3
96 | #NET SDRAM_ADDR(4) LOC="P46" | IOSTANDARD=LVTTL; # SDRAM_ADDR4
97 | #NET SDRAM_ADDR(5) LOC="P45" | IOSTANDARD=LVTTL; # SDRAM_ADDR5
98 | #NET SDRAM_ADDR(6) LOC="P44" | IOSTANDARD=LVTTL; # SDRAM_ADDR6
99 | #NET SDRAM_ADDR(7) LOC="P43" | IOSTANDARD=LVTTL; # SDRAM_ADDR7
100 | #NET SDRAM_ADDR(8) LOC="P41" | IOSTANDARD=LVTTL; # SDRAM_ADDR8
101 | #NET SDRAM_ADDR(9) LOC="P40" | IOSTANDARD=LVTTL; # SDRAM_ADDR9
102 | #NET SDRAM_ADDR(10) LOC="P141" | IOSTANDARD=LVTTL; # SDRAM_ADDR10
103 | #NET SDRAM_ADDR(11) LOC="P35" | IOSTANDARD=LVTTL; # SDRAM_ADDR11
104 | #NET SDRAM_ADDR(12) LOC="P34" | IOSTANDARD=LVTTL; # SDRAM_ADDR12
105 | #NET SDRAM_DATA(0) LOC="P9" | IOSTANDARD=LVTTL; # SDRAM_DATA0
106 | #NET SDRAM_DATA(1) LOC="P10" | IOSTANDARD=LVTTL; # SDRAM_DATA1
107 | #NET SDRAM_DATA(2) LOC="P11" | IOSTANDARD=LVTTL; # SDRAM_DATA2
108 | #NET SDRAM_DATA(3) LOC="P12" | IOSTANDARD=LVTTL; # SDRAM_DATA3
109 | #NET SDRAM_DATA(4) LOC="P14" | IOSTANDARD=LVTTL; # SDRAM_DATA4
110 | #NET SDRAM_DATA(5) LOC="P15" | IOSTANDARD=LVTTL; # SDRAM_DATA5
111 | #NET SDRAM_DATA(6) LOC="P16" | IOSTANDARD=LVTTL; # SDRAM_DATA6
112 | #NET SDRAM_DATA(7) LOC="P8" | IOSTANDARD=LVTTL; # SDRAM_DATA7
113 | #NET SDRAM_DATA(8) LOC="P21" | IOSTANDARD=LVTTL; # SDRAM_DATA8
114 | #NET SDRAM_DATA(9) LOC="P22" | IOSTANDARD=LVTTL; # SDRAM_DATA9
115 | #NET SDRAM_DATA(10) LOC="P23" | IOSTANDARD=LVTTL; # SDRAM_DATA10
116 | #NET SDRAM_DATA(11) LOC="P24" | IOSTANDARD=LVTTL; # SDRAM_DATA11
117 | #NET SDRAM_DATA(12) LOC="P26" | IOSTANDARD=LVTTL; # SDRAM_DATA12
118 | #NET SDRAM_DATA(13) LOC="P27" | IOSTANDARD=LVTTL; # SDRAM_DATA13
119 | #NET SDRAM_DATA(14) LOC="P29" | IOSTANDARD=LVTTL; # SDRAM_DATA14
120 | #NET SDRAM_DATA(15) LOC="P30" | IOSTANDARD=LVTTL; # SDRAM_DATA15
121 | #NET SDRAM_DQML LOC="P7" | IOSTANDARD=LVTTL; # SDRAM_DQML
122 | #NET SDRAM_DQMH LOC="P17" | IOSTANDARD=LVTTL; # SDRAM_DQMH
123 | #NET SDRAM_BA(0) LOC="P143" | IOSTANDARD=LVTTL; # SDRAM_BA0
124 | #NET SDRAM_BA(1) LOC="P142" | IOSTANDARD=LVTTL; # SDRAM_BA1
125 | #NET SDRAM_nWE LOC="P6" | IOSTANDARD=LVTTL; # SDRAM_nWE
126 | #NET SDRAM_nCAS LOC="P5" | IOSTANDARD=LVTTL; # SDRAM_nCAS
127 | #NET SDRAM_nRAS LOC="P2" | IOSTANDARD=LVTTL; # SDRAM_nRAS
128 | #NET SDRAM_CS LOC="P1" | IOSTANDARD=LVTTL; # SDRAM_CS
129 | #NET SDRAM_CLK LOC="P32" | IOSTANDARD=LVTTL; # SDRAM_CLK
130 | #NET SDRAM_CKE LOC="P33" | IOSTANDARD=LVTTL; # SDRAM_CKE
131 | #NET LED1 LOC="P112" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # LED1
132 | #NET JTAG_TMS LOC="P107" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TMS
133 | #NET JTAG_TCK LOC="P109" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TCK
134 | #NET JTAG_TDI LOC="P110" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDI
135 | #NET JTAG_TDO LOC="P106" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDO
136 | #NET FLASH_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS
137 | #NET FLASH_CK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK
138 | #NET FLASH_SI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI
139 | #NET FLASH_SO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # FLASH_SO
140 |
--------------------------------------------------------------------------------
/fpga-synth/fpga.v:
--------------------------------------------------------------------------------
1 | // File: fpga.v
2 | // Generated by MyHDL 0.7
3 | // Date: Thu May 30 00:30:01 2013
4 |
5 |
6 | `timescale 1ns/10ps
7 |
8 | module fpga (
9 | fastclk,
10 | reset,
11 | param_data,
12 | param_clk,
13 | audio_req,
14 | audio_ack,
15 | dac_bit
16 | );
17 |
18 |
19 | input fastclk;
20 | input reset;
21 | input [3:0] param_data;
22 | input param_clk;
23 | input audio_req;
24 | input audio_ack;
25 | output dac_bit;
26 | wire dac_bit;
27 |
28 | reg [3:0] _release;
29 | reg [13:0] threshold;
30 | reg [23:0] input_driver_count;
31 | reg [1:0] select;
32 | reg [3:0] decay;
33 | reg [3:0] attack;
34 | reg [3:0] sustain;
35 | reg [9:0] aclk_counter;
36 | reg keydown;
37 | reg clk;
38 | reg [23:0] delta_phase;
39 | reg signed [13:0] wavgen_output;
40 | wire signed [13:0] drivers_3_interp_result;
41 | reg drivers_3_dac_bit_internal;
42 | reg [13:0] drivers_3_interp_result_unsigned;
43 | reg [15:0] drivers_3_vc_estimate;
44 | reg [31:0] drivers_3_sum_of_products;
45 | reg [13:0] drivers_3_things_4___out;
46 | reg signed [29:0] drivers_3_things_0_interp_step;
47 | reg signed [29:0] drivers_3_things_0_interp_data;
48 | reg signed [13:0] drivers_3_things_0_delay_1;
49 | wire signed [13:0] drivers_3_things_0_x;
50 | reg [12:0] drivers_2_noise_register_13;
51 | reg [23:0] drivers_2_phase_counter;
52 | reg [15:0] drivers_2_noise_register_16;
53 |
54 |
55 |
56 |
57 |
58 | always @(posedge fastclk, posedge reset) begin: FPGA_DRIVERS_0
59 | if (reset) begin
60 | aclk_counter <= 0;
61 | clk <= 1'b1;
62 | end
63 | else if ((aclk_counter >= 800)) begin
64 | aclk_counter <= 0;
65 | clk <= 1'b1;
66 | end
67 | else begin
68 | aclk_counter <= (aclk_counter + 1);
69 | clk <= 1'b0;
70 | end
71 | end
72 |
73 |
74 | always @(posedge clk, posedge reset) begin: FPGA_DRIVE_INPUTS
75 | attack <= 3;
76 | decay <= 5;
77 | sustain <= 8;
78 | _release <= 0;
79 | delta_phase <= 184549;
80 | select <= 1;
81 | threshold <= 8192;
82 | keydown <= 0;
83 | if (reset) begin
84 | keydown <= 0;
85 | input_driver_count <= 0;
86 | end
87 | else if ((input_driver_count >= (5 * 40000))) begin
88 | keydown <= 0;
89 | input_driver_count <= 0;
90 | end
91 | else if ((input_driver_count < (2 * 40000))) begin
92 | keydown <= 1;
93 | input_driver_count <= (input_driver_count + 1);
94 | end
95 | else begin
96 | keydown <= 0;
97 | input_driver_count <= (input_driver_count + 1);
98 | end
99 | end
100 |
101 |
102 | always @(posedge clk, posedge reset) begin: FPGA_DRIVERS_2_WAVEFORMS
103 | if (reset) begin
104 | drivers_2_noise_register_16 <= 123;
105 | drivers_2_noise_register_13 <= 1787;
106 | drivers_2_phase_counter <= 0;
107 | wavgen_output <= 0;
108 | end
109 | else begin
110 | if ((drivers_2_noise_register_16 == 0)) begin
111 | drivers_2_noise_register_16 <= 123;
112 | end
113 | else if (((((drivers_2_noise_register_16 ^ (drivers_2_noise_register_16 >>> 2)) ^ (drivers_2_noise_register_16 >>> 3)) ^ (drivers_2_noise_register_16 >>> 5)) & 1)) begin
114 | drivers_2_noise_register_16 <= ((1 << 15) + (drivers_2_noise_register_16 >>> 1));
115 | end
116 | else begin
117 | drivers_2_noise_register_16 <= (drivers_2_noise_register_16 >>> 1);
118 | end
119 | if ((drivers_2_noise_register_13 == 0)) begin
120 | drivers_2_noise_register_13 <= 1787;
121 | end
122 | else if (((((drivers_2_noise_register_13 ^ (drivers_2_noise_register_13 >>> 1)) ^ (drivers_2_noise_register_13 >>> 2)) ^ (drivers_2_noise_register_13 >>> 5)) & 1)) begin
123 | drivers_2_noise_register_13 <= ((1 << 12) + (drivers_2_noise_register_13 >>> 1));
124 | end
125 | else begin
126 | drivers_2_noise_register_13 <= (drivers_2_noise_register_13 >>> 1);
127 | end
128 | if (((drivers_2_phase_counter + delta_phase) >= (1 << 24))) begin
129 | drivers_2_phase_counter <= ((drivers_2_phase_counter + delta_phase) - (1 << 24));
130 | end
131 | else begin
132 | drivers_2_phase_counter <= (drivers_2_phase_counter + delta_phase);
133 | end
134 | case (select)
135 | 'h0: begin
136 | wavgen_output <= ((drivers_2_phase_counter - 8388608) >>> 10);
137 | end
138 | 'h1: begin
139 | if ((drivers_2_phase_counter < 8388608)) begin
140 | wavgen_output <= ((drivers_2_phase_counter - 4194304) >>> 9);
141 | end
142 | else begin
143 | wavgen_output <= ((12582912 - drivers_2_phase_counter) >>> 9);
144 | end
145 | end
146 | 'h2: begin
147 | if ((drivers_2_phase_counter > (threshold << (24 - 14)))) begin
148 | wavgen_output <= (16383 - 8192);
149 | end
150 | else begin
151 | wavgen_output <= (-8192);
152 | end
153 | end
154 | default: begin
155 | wavgen_output <= (((drivers_2_noise_register_16 ^ drivers_2_noise_register_13) & 16383) - 8192);
156 | end
157 | endcase
158 | end
159 | end
160 |
161 |
162 | always @(posedge fastclk, posedge reset) begin: FPGA_DRIVERS_3_THINGS_0_DO_STUFF
163 | if (reset) begin
164 | drivers_3_things_0_delay_1 <= 0;
165 | drivers_3_things_0_interp_data <= 0;
166 | drivers_3_things_0_interp_step <= 0;
167 | end
168 | else begin
169 | if (clk) begin
170 | drivers_3_things_0_interp_data <= (drivers_3_things_0_delay_1 << 16);
171 | drivers_3_things_0_delay_1 <= wavgen_output;
172 | drivers_3_things_0_interp_step <= ((((((((drivers_3_things_0_x << 12) + (drivers_3_things_0_x << 10)) + (drivers_3_things_0_x << 6)) + (drivers_3_things_0_x << 5)) + (drivers_3_things_0_x << 4)) + (drivers_3_things_0_x << 3)) + (drivers_3_things_0_x << 1)) + drivers_3_things_0_x);
173 | end
174 | else if (((drivers_3_things_0_interp_data + drivers_3_things_0_interp_step) < -536870912)) begin
175 | drivers_3_things_0_interp_data <= -536870912;
176 | end
177 | else if (((drivers_3_things_0_interp_data + drivers_3_things_0_interp_step) >= 536870912)) begin
178 | drivers_3_things_0_interp_data <= (536870912 - 1);
179 | end
180 | else begin
181 | drivers_3_things_0_interp_data <= (drivers_3_things_0_interp_data + drivers_3_things_0_interp_step);
182 | end
183 | end
184 | end
185 |
186 |
187 |
188 | assign drivers_3_things_0_x = (wavgen_output - drivers_3_things_0_delay_1);
189 | assign drivers_3_interp_result = $signed(drivers_3_things_0_interp_data >>> 16);
190 |
191 |
192 |
193 | assign dac_bit = drivers_3_dac_bit_internal;
194 |
195 |
196 | always @(posedge fastclk, posedge reset) begin: FPGA_DRIVERS_3_DO_STUFF
197 | if (reset) begin
198 | drivers_3_dac_bit_internal <= 0;
199 | drivers_3_vc_estimate <= (1 << 15);
200 | end
201 | else begin
202 | drivers_3_dac_bit_internal <= (drivers_3_interp_result_unsigned > (drivers_3_sum_of_products >>> (32 - 14)));
203 | drivers_3_vc_estimate <= (drivers_3_sum_of_products >>> 16);
204 | end
205 | end
206 |
207 |
208 | always @(drivers_3_dac_bit_internal, drivers_3_vc_estimate) begin: FPGA_DRIVERS_3_MULTIPLY
209 | if (drivers_3_dac_bit_internal) begin
210 | if (((13400823 + (65332 * drivers_3_vc_estimate)) >= (1 << 32))) begin
211 | drivers_3_sum_of_products = ((1 << 32) - 1);
212 | end
213 | else begin
214 | drivers_3_sum_of_products = (13400823 + (65332 * drivers_3_vc_estimate));
215 | end
216 | end
217 | else begin
218 | drivers_3_sum_of_products = (65332 * drivers_3_vc_estimate);
219 | end
220 | end
221 |
222 |
223 | always @(drivers_3_interp_result) begin: FPGA_DRIVERS_3_THINGS_4_DRIVE__OUT
224 | drivers_3_things_4___out <= (drivers_3_interp_result + (1 << (14 - 1)));
225 | end
226 |
227 |
228 | always @(drivers_3_things_4___out) begin: FPGA_DRIVERS_3_THINGS_4_DRIVE_OUT
229 | drivers_3_interp_result_unsigned <= drivers_3_things_4___out;
230 | end
231 |
232 | endmodule
233 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/555_Monostable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wware/fpga-synth/4d5eadcf3c092baa03ca7508b388afbe2783aef3/fpga-synth/instrument/555_Monostable.png
--------------------------------------------------------------------------------
/fpga-synth/instrument/README.rst:
--------------------------------------------------------------------------------
1 | An electronic musical instrument
2 | ================================
3 |
4 | The stuff below is the thinking I was doing a few months back. Then I had the
5 | idea of making a FPGA board for either the Raspberry Pi or Beaglebone Black
6 | which would be a sort of audio coprocessor, with stereo 14-bit serial ADCs and
7 | DACs, with a sort of DSP-ish instruction set, and the hardware for the board
8 | mostly following the hardware on the Papilio Pro. So I noodled around with that
9 | idea, and realized that in order to make it generally programmable with a lot
10 | of hardware parallelism was to have an impossibly large crossbar switch. So
11 | that idea is shelved for later, and I'm back to specifically a music
12 | synthesizer.
13 |
14 | I foresook the Raspberry Pi because I had been reading about how impoverished
15 | it is for GPIO pins, and I figured that would be horrible for trying to get
16 | parameters and control signals in and out of the FPGA. But now I'm inclined to
17 | think that SPI should be fast enough, so I'm going down that route for a while.
18 |
19 | Meanwhile I'm also planning to rework the Python/MyHDL code a bit. I want to
20 | give more thought to design for testability, both in the design phase (when
21 | "test" means unit tests and simulations) and in silico (when "test" might mean
22 | something more like halting all the clocks and pulling out information via
23 | JTAG).
24 |
25 | Earlier thoughts
26 | ----------------
27 |
28 | The ultimate goal of the FPGA synthesizer work is to build a self-contained
29 | electronic musical instrument. When I first started thinking about it at in my
30 | twenties, I envisioned building it into a piece of PVC tubing four or five long
31 | which would be held like a cello.
32 |
33 | When I discovered that Sparkfun sells a somewhat novel sound transducer (one
34 | large_ and one small_), I reconsidered the physical design to be something more
35 | like a lute or guitar. Given the limits of my carpentry skills, I'm planning on
36 | a tetrahedral body made of 1/4" plywood where one corner of the tetrahedron is
37 | all right angles, to limit the number of strange angles I need to deal with.
38 | It should be possible to cut out the plywood triangles easily on a laser cutter
39 | at `danger!awesome`_. They now offer `DIY cutting`_ if you take a safety class,
40 | which is potentially worthwhile.
41 |
42 | The sounding hole (or on a lute, the rosette) will be a `Sierpinski triangle`_
43 | design, scaled to be similar to the triangle forming the playing surface, and
44 | situated symmetrically on that surface.
45 |
46 | .. _`large`: https://www.sparkfun.com/products/10975
47 | .. _`small`: https://www.sparkfun.com/products/10917
48 | .. _`danger!awesome`: http://www.dangerawesome.co/
49 | .. _`DIY cutting`: http://www.dangerawesome.co/2013/03/diy-lasering/
50 | .. _`Sierpinski triangle`: http://en.wikipedia.org/wiki/Sierpinski_triangle
51 |
52 | The touch-sensitive keyboard
53 | ----------------------------
54 |
55 | In college I built a very cool touch-sensitive keyboard that scanned the keys
56 | watching for the capacitance of the human body. I've since learned that I can
57 | detect a light or heavy touch by seeing a smaller or larger capacitance, and it
58 | is easily translated into a measurable pulse width. I'm planning on either a
59 | three-octave 37-key keyboard or a four-octave 49-key keyboard. Each key is
60 | connected to one pin of a CD4051_ analog multiplexer, and only one of the
61 | CD4051s is enabled at a time, so each key is scanned individually. A short
62 | low-going pulse is applied to the trigger input of a `555 timer IC`_ in
63 | `monostable mode`_ and its threshold and discharge pins are tied to a pull-up resistor, and
64 | routed through the CD4051 to one of the keys. When you touch the key, it
65 | behaves like a capacitor to ground, increasing the output pulse width. The more
66 | firmly you touch the key, the bigger the pulse width. The trigger pulse needs
67 | to be shorter than the shortest expected RC time constant. Building the circuit
68 | on a `solderless breadboard`_ with a 100K pull-up, I see a pulse width of 4
69 | microseconds when not touching it, and about 12 microseconds when touching it
70 | firmly. This indicates a parasitic capacitance on the breadboard of about 360
71 | picofarads, and a total of about 1000 picofarads when touching firmly. I can
72 | get a lower parasitic capacitance by replacing the breadboard with something
73 | sparser. The touch capacitance will change a bit when protecting the copper key
74 | with a layer of sealant_. I don't want the copper turning green after a few
75 | months or years of playing. I'm going to need to physically mock up a key to
76 | study realistic conditions, including putting on the sealant.
77 |
78 | The time period is measured by a CPLD_ (which pulses the 555 and controls the
79 | CD4051s), probably `this one`_ since it's powerful, affordable, and is already on
80 | a breakout board. It has 256 macrocells so it can hang onto all the key codes
81 | while scanning, and the RPi can fetch them later. (There has been `some FPGA
82 | work`_ done with the Raspberry Pi.) Pulse widths can be encoded into just two or
83 | three bits per key, and the RPi can notice how quickly the pulse width
84 | increases, and convert that to a `MIDI key velocity`_.
85 |
86 | The keyboard_ will be comprised of short lengths of 14-AWG solid bare copper
87 | electrical wire running along the surface of the PVC in the pattern shown at
88 | right. To make the case look as good as possible, I'll drill the holes for the
89 | wire before I paint the PVC. Then put in the wires, then apply the sealant.
90 |
91 | Monostable mode for the 555
92 | ---------------------------
93 |
94 | .. image:: 555_Monostable.png
95 | :alt: 555 schematic
96 |
97 | Keyboard layout
98 | ---------------
99 |
100 | .. image:: http://upload.wikimedia.org/wikipedia/en/0/0b/Wware-rotated-keyboard-small.png
101 | :alt: Keyboard layout
102 |
103 | .. _`CD4051`: http://www.datasheetcatalog.org/datasheets/208/109138_DS.pdf
104 | .. _`555 timer IC`: http://en.wikipedia.org/wiki/555_timer_IC
105 | .. _`monostable mode`: http://en.wikipedia.org/wiki/555_timer_IC#Monostable
106 | .. _`solderless breadboard`: http://en.wikipedia.org/wiki/Breadboard#Solderless_breadboard
107 | .. _`sealant`: http://www.krylon.com/products/make_it_last_clear_sealer/
108 | .. _`CPLD`: http://en.wikipedia.org/wiki/Complex_programmable_logic_device
109 | .. _`this one`: http://www.digikey.com/product-detail/en/LC4256ZE-B-EVN/220-1146-ND/2641947
110 | .. _`some FPGA work`: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=9085&p=173976
111 | .. _`MIDI key velocity`: http://www.blitter.com/~russtopia/MIDI/~jglatt/tech/midispec/noteon.htm
112 | .. _`keyboard`: http://en.wikipedia.org/wiki/Musical_keyboard
113 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/body.py:
--------------------------------------------------------------------------------
1 | import pslib
2 |
3 | page = pslib.PostscriptPage()
4 |
5 | A = 24
6 | B = 12
7 |
8 | SQRT2 = 2 ** 0.5
9 |
10 | C = (A**2 - 0.5 * B**2)**.5 + B / SQRT2
11 | D = (A**2 - B**2)**.5
12 |
13 | page.add_polygon(pslib.Point(0, B / SQRT2),
14 | pslib.Point(B / SQRT2, 0),
15 | pslib.Point(B * SQRT2, B / SQRT2))
16 |
17 | page.add_polygon(pslib.Point(0, B / SQRT2),
18 | pslib.Point(B, B / SQRT2),
19 | pslib.Point(B, D + B / SQRT2))
20 |
21 | page.add_polygon(pslib.Point(2 * B, B / SQRT2),
22 | pslib.Point(B, B / SQRT2),
23 | pslib.Point(B, D + B / SQRT2))
24 |
25 | a = pslib.Point(2 * B, B / SQRT2)
26 | b = pslib.Point(2 * B - B / SQRT2, C)
27 | c = pslib.Point(2 * B + B / SQRT2, C)
28 | d = pslib.Point.average(a, b, c)
29 |
30 | page.add_polygon(a, b, c)
31 |
32 | h = 0.4
33 | a1 = h * a + (1 - h) * d
34 | b1 = h * b + (1 - h) * d
35 | c1 = h * c + (1 - h) * d
36 |
37 | apply(page.add_paths, pslib.sierpinski(a1, b1, c1, depth=3, gap=0.5))
38 |
39 | page.transform(pslib.PS_SPACE.rescale(0.2).translate(pslib.Point(1, 1))).render()
40 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/musicbox.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """\
4 | MyHDL code for music-box mode of the FPGA synthesizer
5 |
6 | Usage:
7 | PROG [options]
8 |
9 | Options:
10 | -s --sim run a simulation
11 | -h --hdl generate Verilog
12 | -t --unit-test run unit tests
13 | """
14 |
15 | import docopt
16 | import sys
17 | from myhdl import *
18 |
19 | options = docopt.docopt(__doc__.replace('PROG', sys.argv[0]))
20 |
21 |
22 | def genclocks(clk, clk40, clk2):
23 | """
24 | Given a 32 MHz clock, generate clocks at 40 kHz and 2 Hz.
25 | """
26 | counter1 = Signal(intbv(0)[10:])
27 | counter2 = Signal(intbv(0)[15:])
28 |
29 | @always(clk.posedge)
30 | def foo():
31 | if counter1 >= 799:
32 | clk40.next = 1
33 | counter1.next = 0
34 | if counter2 >= 19999:
35 | counter2.next = 0
36 | clk2.next = 0
37 | elif counter2 == 1:
38 | counter2.next = counter2 + 1
39 | clk2.next = 1
40 | else:
41 | counter2.next = counter2 + 1
42 | clk2.next = 0
43 | else:
44 | counter1.next = counter1 + 1
45 | clk40.next = 0
46 | clk2.next = 0
47 |
48 | return foo
49 |
50 |
51 | # Calculate dphase values for the white piano keys for 3 octaves, not
52 | # including the highest C.
53 | if sys.argv[1:2] == ['calculate']:
54 | k = (440. * (1<<24) / 40000) / (2 ** 0.75)
55 | j = 0
56 | for octave in range(3):
57 | for i in (0, 2, 4, 5, 7, 9, 11):
58 | p = 12.0 * octave + i
59 | count = (2.0 ** (p / 12)) * k
60 | print j, int(count + 0.5)
61 | j += 1
62 | sys.exit(0)
63 |
64 |
65 | def get_freq(clk, pitch, freq):
66 | """
67 | Using dphase values above, map pitch (as an index of the white piano keys)
68 | to dphase value, from middle C to the C two octaves higher.
69 | """
70 | @always(clk.posedge)
71 | def foo():
72 | if pitch == 0:
73 | freq.next = 109734
74 | elif pitch == 1:
75 | freq.next = 123172
76 | elif pitch == 2:
77 | freq.next = 138256
78 | elif pitch == 3:
79 | freq.next = 146477
80 | elif pitch == 4:
81 | freq.next = 164415
82 | elif pitch == 5:
83 | freq.next = 184549
84 | elif pitch == 6:
85 | freq.next = 207150
86 | elif pitch == 7:
87 | freq.next = 219467
88 | elif pitch == 8:
89 | freq.next = 246344
90 | elif pitch == 9:
91 | freq.next = 276512
92 | elif pitch == 10:
93 | freq.next = 292954
94 | elif pitch == 11:
95 | freq.next = 328830
96 | elif pitch == 12:
97 | freq.next = 369099
98 | elif pitch == 13:
99 | freq.next = 414299
100 | elif pitch == 14:
101 | freq.next = 438935
102 | else:
103 | freq.next = 0
104 | return foo
105 |
106 |
107 | def voice(clk, clk40, keydn, dphase, _out):
108 | ampl = Signal(intbv(0)[14:])
109 | phase = Signal(intbv(0)[24:])
110 | twave = Signal(intbv(0)[14:])
111 |
112 | @always(clk.posedge)
113 | def piece1():
114 | if keydn:
115 | ampl.next = 16383
116 | if clk40:
117 | if ampl > 0:
118 | ampl.next = ampl - 1
119 | phase.next = (phase + dphase) & ((1 << 24) - 1)
120 | if (phase & (1 << 23)) != 0:
121 | twave.next = ((1 << 24) - 1 - phase) >> 9
122 | else:
123 | twave.next = phase >> 9
124 | # ampl is unsigned, twave is signed. This is how you multiply a
125 | # signed int by an unsigned int to get a signed result.
126 | _out.next = ((((1<<14) - 1 - ampl) << 13) + ampl * twave) >> 14
127 |
128 | return piece1
129 |
130 |
131 | def dacwriter(clk, clk40, dac_data, dacbit, cs_active):
132 | dac_counter = Signal(intbv(0)[4:])
133 | dac_data_latched = Signal(intbv(0)[14:])
134 |
135 | @always_comb
136 | def drive_dacbit():
137 | if dac_counter < 14:
138 | dacbit.next = ((dac_data_latched >> (13 - dac_counter)) & 1) != 0
139 | else:
140 | dacbit.next = 0
141 |
142 | @always(clk.posedge)
143 | def count():
144 | if clk40:
145 | dac_counter.next = 0
146 | cs_active.next = 1
147 | dac_data_latched.next = dac_data
148 | elif dac_counter < 16:
149 | if dac_counter == 15:
150 | cs_active.next = 0
151 | dac_counter.next = (dac_counter + 1) & 15
152 |
153 | return (count, drive_dacbit)
154 |
155 |
156 | def tune(clk, clk40, clk2, dphase1, dphase2, dphase3, keydn1, keydn2, keydn3):
157 | pitch1, pitch2, pitch3 = [Signal(intbv(0)[5:]) for i in range(3)]
158 | tunestep = Signal(intbv(0)[4:])
159 |
160 | f1 = get_freq(clk, pitch1, dphase1)
161 | f2 = get_freq(clk, pitch2, dphase2)
162 | f3 = get_freq(clk, pitch3, dphase3)
163 |
164 | @always(clk.posedge)
165 | def foo():
166 | if clk2:
167 | if tunestep == 0:
168 | pitch1.next = 0
169 | keydn1.next = 1
170 | pitch2.next = 4
171 | keydn2.next = 1
172 | pitch3.next = 9
173 | keydn3.next = 1
174 | elif tunestep == 1:
175 | pitch1.next = 2
176 | keydn1.next = 1
177 | elif tunestep == 2:
178 | pitch1.next = 4
179 | keydn1.next = 1
180 | elif tunestep == 3:
181 | pitch1.next = 0
182 | keydn1.next = 1
183 | pitch2.next = 5
184 | keydn2.next = 1
185 | pitch3.next = 10
186 | keydn3.next = 1
187 | elif tunestep == 4:
188 | pitch1.next = 3
189 | keydn1.next = 1
190 | elif tunestep == 5:
191 | pitch1.next = 5
192 | keydn1.next = 1
193 | elif tunestep == 6:
194 | pitch1.next = 1
195 | keydn1.next = 1
196 | pitch2.next = 6
197 | keydn2.next = 1
198 | pitch3.next = 11
199 | keydn3.next = 1
200 | elif tunestep == 7:
201 | pitch1.next = 4
202 | keydn1.next = 1
203 | elif tunestep == 8:
204 | pitch1.next = 6
205 | keydn1.next = 1
206 | elif tunestep == 9:
207 | pitch1.next = 7
208 | keydn1.next = 1
209 | pitch2.next = 9
210 | keydn2.next = 1
211 | pitch3.next = 11
212 | keydn3.next = 1
213 |
214 | if tunestep < 12:
215 | tunestep.next = tunestep + 1
216 | else:
217 | tunestep.next = 0
218 | else:
219 | keydn1.next = 0
220 | keydn2.next = 0
221 | keydn3.next = 0
222 |
223 | @always(clk)
224 | def foo2():
225 | pitch1.next = 0
226 | keydn1.next = 1
227 | pitch2.next = 7
228 | keydn2.next = 1
229 | pitch3.next = 16
230 | keydn3.next = 1
231 |
232 | return (foo, f1, f2, f3)
233 |
234 |
235 | def fpga(clk, out_a, out_b, out_c, out_d):
236 | clk40 = Signal(False)
237 | clk2 = Signal(False)
238 | cs_active = Signal(False)
239 | outb_internal = Signal(False)
240 | _out = Signal(intbv(0)[14:])
241 | _out1, _out2, _out3 = [Signal(intbv(0)[14:]) for i in range(3)]
242 | dphase1, dphase2, dphase3 = [Signal(intbv(0)[24:]) for i in range(3)]
243 | keydn1, keydn2, keydn3 = [Signal(False) for i in range(3)]
244 |
245 | g = genclocks(clk, clk40, clk2)
246 | dw = dacwriter(clk, clk40, _out, outb_internal, cs_active)
247 | t = tune(clk, clk40, clk2, dphase1, dphase2, dphase3, keydn1, keydn2, keydn3)
248 |
249 | v1 = voice(clk, clk40, keydn1, dphase1, _out1)
250 | v2 = voice(clk, clk40, keydn2, dphase2, _out2)
251 | v3 = voice(clk, clk40, keydn3, dphase3, _out3)
252 |
253 | @always_comb
254 | def out_acd():
255 | #_out.next = (_out1 + _out2 + _out3) >> 2
256 | _out.next = (_out1 >> 2) + (_out2 >> 2) + (_out3 >> 2)
257 | out_b.next = outb_internal
258 | out_a.next = 0
259 | out_c.next = not clk
260 | out_d.next = not cs_active
261 |
262 | return (g, dw, t, out_acd, v1, v2, v3)
263 |
264 |
265 | def simulate():
266 | out_a, out_b, out_c, out_d = [Signal(False) for i in range(4)]
267 | clk = Signal(False)
268 | _fpga = fpga(clk, out_a, out_b, out_c, out_d)
269 |
270 | @instance
271 | def bench():
272 | clk.next = 0
273 | for i in range(1000000):
274 | yield delay(1)
275 | clk.next = 1
276 | yield delay(1)
277 | clk.next = 0
278 |
279 | return (bench, _fpga)
280 |
281 |
282 | if options['--hdl']:
283 | out_a, out_b, out_c, out_d = [Signal(False) for i in range(4)]
284 | clk = Signal(False)
285 | toVerilog(fpga, clk, out_a, out_b, out_c, out_d)
286 |
287 | if options['--sim']:
288 | Simulation(traceSignals(simulate)).run()
289 |
290 | if options['--unit-test']:
291 | raise Exception('not implemented yet')
292 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/musicbox.xise:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/ppro.ucf:
--------------------------------------------------------------------------------
1 | # UCF file for the Papilio Pro board
2 | # Generated by pin_converter, written by Kevin Lindsey
3 | # https://github.com/thelonious/papilio_pins/tree/development/pin_converter
4 |
5 | # Main board wing pin [] to FPGA pin Pxx map
6 | # -------C------- -------B------- -------A-------
7 | # [GND] [C00] P114 [GND] [B00] P99 P100 [A15]
8 | # [2V5] [C01] P115 [2V5] [B01] P97 P98 [A14]
9 | # [3V3] [C02] P116 [3V3] [B02] P92 P93 [A13]
10 | # [5V0] [C03] P117 [5V0] [B03] P87 P88 [A12]
11 | # [C04] P118 [B04] P84 P85 [A11] [5V0]
12 | # [C05] P119 [B05] P82 P83 [A10] [3V3]
13 | # [C06] P120 [B06] P80 P81 [A09] [2V5]
14 | # [C07] P121 [B07] P78 P79 [A08] [GND]
15 | # [GND] [C08] P123 [GND] [B08] P74 P75 [A07]
16 | # [2V5] [C09] P124 [2V5] [B09] P95 P67 [A06]
17 | # [3V3] [C10] P126 [3V3] [B10] P62 P66 [A05]
18 | # [5V0] [C11] P127 [5V0] [B11] P59 P61 [A04]
19 | # [C12] P131 [B12] P57 P58 [A03] [5V0]
20 | # [C13] P132 [B13] P55 P56 [A02] [3V3]
21 | # [C14] P133 [B14] P50 P51 [A01] [2V5]
22 | # [C15] P134 [B15] P47 P48 [A00] [GND]
23 |
24 | ## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
25 | CONFIG PROHIBIT=P144;
26 | CONFIG PROHIBIT=P69;
27 | CONFIG PROHIBIT=P60;
28 |
29 | NET CLK LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
30 | #NET RX LOC="P101" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # RX
31 | #NET TX LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # TX
32 | NET out_a LOC="P48" | IOSTANDARD=LVTTL; # A0
33 | NET out_b LOC="P51" | IOSTANDARD=LVTTL; # A1
34 | NET out_c LOC="P56" | IOSTANDARD=LVTTL; # A2
35 | NET out_d LOC="P58" | IOSTANDARD=LVTTL; # A3
36 | #NET A(0) LOC="P48" | IOSTANDARD=LVTTL; # A0
37 | #NET A(1) LOC="P51" | IOSTANDARD=LVTTL; # A1
38 | #NET A(2) LOC="P56" | IOSTANDARD=LVTTL; # A2
39 | #NET A(3) LOC="P58" | IOSTANDARD=LVTTL; # A3
40 | #NET A(4) LOC="P61" | IOSTANDARD=LVTTL; # A4
41 | #NET A(5) LOC="P66" | IOSTANDARD=LVTTL; # A5
42 | #NET A(6) LOC="P67" | IOSTANDARD=LVTTL; # A6
43 | #NET A(7) LOC="P75" | IOSTANDARD=LVTTL; # A7
44 | #NET A(8) LOC="P79" | IOSTANDARD=LVTTL; # A8
45 | #NET A(9) LOC="P81" | IOSTANDARD=LVTTL; # A9
46 | #NET A(10) LOC="P83" | IOSTANDARD=LVTTL; # A10
47 | #NET A(11) LOC="P85" | IOSTANDARD=LVTTL; # A11
48 | #NET A(12) LOC="P88" | IOSTANDARD=LVTTL; # A12
49 | #NET A(13) LOC="P93" | IOSTANDARD=LVTTL; # A13
50 | #NET A(14) LOC="P98" | IOSTANDARD=LVTTL; # A14
51 | #NET A(15) LOC="P100" | IOSTANDARD=LVTTL; # A15
52 | #NET B(0) LOC="P99" | IOSTANDARD=LVTTL; # B0
53 | #NET B(1) LOC="P97" | IOSTANDARD=LVTTL; # B1
54 | #NET B(2) LOC="P92" | IOSTANDARD=LVTTL; # B2
55 | #NET B(3) LOC="P87" | IOSTANDARD=LVTTL; # B3
56 | #NET B(4) LOC="P84" | IOSTANDARD=LVTTL; # B4
57 | #NET B(5) LOC="P82" | IOSTANDARD=LVTTL; # B5
58 | #NET B(6) LOC="P80" | IOSTANDARD=LVTTL; # B6
59 | #NET B(7) LOC="P78" | IOSTANDARD=LVTTL; # B7
60 | #NET B(8) LOC="P74" | IOSTANDARD=LVTTL; # B8
61 | #NET B(9) LOC="P95" | IOSTANDARD=LVTTL; # B9
62 | #NET B(10) LOC="P62" | IOSTANDARD=LVTTL; # B10
63 | #NET B(11) LOC="P59" | IOSTANDARD=LVTTL; # B11
64 | #NET B(12) LOC="P57" | IOSTANDARD=LVTTL; # B12
65 | #NET B(13) LOC="P55" | IOSTANDARD=LVTTL; # B13
66 | #NET B(14) LOC="P50" | IOSTANDARD=LVTTL; # B14
67 | #NET B(15) LOC="P47" | IOSTANDARD=LVTTL; # B15
68 | #NET C(0) LOC="P114" | IOSTANDARD=LVTTL; # C0
69 | #NET C(1) LOC="P115" | IOSTANDARD=LVTTL; # C1
70 | #NET C(2) LOC="P116" | IOSTANDARD=LVTTL; # C2
71 | #NET C(3) LOC="P117" | IOSTANDARD=LVTTL; # C3
72 | #NET C(4) LOC="P118" | IOSTANDARD=LVTTL; # C4
73 | #NET C(5) LOC="P119" | IOSTANDARD=LVTTL; # C5
74 | #NET C(6) LOC="P120" | IOSTANDARD=LVTTL; # C6
75 | #NET C(7) LOC="P121" | IOSTANDARD=LVTTL; # C7
76 | #NET C(8) LOC="P123" | IOSTANDARD=LVTTL; # C8
77 | #NET C(9) LOC="P124" | IOSTANDARD=LVTTL; # C9
78 | #NET C(10) LOC="P126" | IOSTANDARD=LVTTL; # C10
79 | #NET C(11) LOC="P127" | IOSTANDARD=LVTTL; # C11
80 | #NET C(12) LOC="P131" | IOSTANDARD=LVTTL; # C12
81 | #NET C(13) LOC="P132" | IOSTANDARD=LVTTL; # C13
82 | #NET C(14) LOC="P133" | IOSTANDARD=LVTTL; # C14
83 | #NET C(15) LOC="P134" | IOSTANDARD=LVTTL; # C15
84 | #NET SDRAM_ADDR(0) LOC="P140" | IOSTANDARD=LVTTL; # SDRAM_ADDR0
85 | #NET SDRAM_ADDR(1) LOC="P139" | IOSTANDARD=LVTTL; # SDRAM_ADDR1
86 | #NET SDRAM_ADDR(2) LOC="P138" | IOSTANDARD=LVTTL; # SDRAM_ADDR2
87 | #NET SDRAM_ADDR(3) LOC="P137" | IOSTANDARD=LVTTL; # SDRAM_ADDR3
88 | #NET SDRAM_ADDR(4) LOC="P46" | IOSTANDARD=LVTTL; # SDRAM_ADDR4
89 | #NET SDRAM_ADDR(5) LOC="P45" | IOSTANDARD=LVTTL; # SDRAM_ADDR5
90 | #NET SDRAM_ADDR(6) LOC="P44" | IOSTANDARD=LVTTL; # SDRAM_ADDR6
91 | #NET SDRAM_ADDR(7) LOC="P43" | IOSTANDARD=LVTTL; # SDRAM_ADDR7
92 | #NET SDRAM_ADDR(8) LOC="P41" | IOSTANDARD=LVTTL; # SDRAM_ADDR8
93 | #NET SDRAM_ADDR(9) LOC="P40" | IOSTANDARD=LVTTL; # SDRAM_ADDR9
94 | #NET SDRAM_ADDR(10) LOC="P141" | IOSTANDARD=LVTTL; # SDRAM_ADDR10
95 | #NET SDRAM_ADDR(11) LOC="P35" | IOSTANDARD=LVTTL; # SDRAM_ADDR11
96 | #NET SDRAM_ADDR(12) LOC="P34" | IOSTANDARD=LVTTL; # SDRAM_ADDR12
97 | #NET SDRAM_DATA(0) LOC="P9" | IOSTANDARD=LVTTL; # SDRAM_DATA0
98 | #NET SDRAM_DATA(1) LOC="P10" | IOSTANDARD=LVTTL; # SDRAM_DATA1
99 | #NET SDRAM_DATA(2) LOC="P11" | IOSTANDARD=LVTTL; # SDRAM_DATA2
100 | #NET SDRAM_DATA(3) LOC="P12" | IOSTANDARD=LVTTL; # SDRAM_DATA3
101 | #NET SDRAM_DATA(4) LOC="P14" | IOSTANDARD=LVTTL; # SDRAM_DATA4
102 | #NET SDRAM_DATA(5) LOC="P15" | IOSTANDARD=LVTTL; # SDRAM_DATA5
103 | #NET SDRAM_DATA(6) LOC="P16" | IOSTANDARD=LVTTL; # SDRAM_DATA6
104 | #NET SDRAM_DATA(7) LOC="P8" | IOSTANDARD=LVTTL; # SDRAM_DATA7
105 | #NET SDRAM_DATA(8) LOC="P21" | IOSTANDARD=LVTTL; # SDRAM_DATA8
106 | #NET SDRAM_DATA(9) LOC="P22" | IOSTANDARD=LVTTL; # SDRAM_DATA9
107 | #NET SDRAM_DATA(10) LOC="P23" | IOSTANDARD=LVTTL; # SDRAM_DATA10
108 | #NET SDRAM_DATA(11) LOC="P24" | IOSTANDARD=LVTTL; # SDRAM_DATA11
109 | #NET SDRAM_DATA(12) LOC="P26" | IOSTANDARD=LVTTL; # SDRAM_DATA12
110 | #NET SDRAM_DATA(13) LOC="P27" | IOSTANDARD=LVTTL; # SDRAM_DATA13
111 | #NET SDRAM_DATA(14) LOC="P29" | IOSTANDARD=LVTTL; # SDRAM_DATA14
112 | #NET SDRAM_DATA(15) LOC="P30" | IOSTANDARD=LVTTL; # SDRAM_DATA15
113 | #NET SDRAM_DQML LOC="P7" | IOSTANDARD=LVTTL; # SDRAM_DQML
114 | #NET SDRAM_DQMH LOC="P17" | IOSTANDARD=LVTTL; # SDRAM_DQMH
115 | #NET SDRAM_BA(0) LOC="P143" | IOSTANDARD=LVTTL; # SDRAM_BA0
116 | #NET SDRAM_BA(1) LOC="P142" | IOSTANDARD=LVTTL; # SDRAM_BA1
117 | #NET SDRAM_nWE LOC="P6" | IOSTANDARD=LVTTL; # SDRAM_nWE
118 | #NET SDRAM_nCAS LOC="P5" | IOSTANDARD=LVTTL; # SDRAM_nCAS
119 | #NET SDRAM_nRAS LOC="P2" | IOSTANDARD=LVTTL; # SDRAM_nRAS
120 | #NET SDRAM_CS LOC="P1" | IOSTANDARD=LVTTL; # SDRAM_CS
121 | #NET SDRAM_CLK LOC="P32" | IOSTANDARD=LVTTL; # SDRAM_CLK
122 | #NET SDRAM_CKE LOC="P33" | IOSTANDARD=LVTTL; # SDRAM_CKE
123 | #NET LED1 LOC="P112" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # LED1
124 | #NET JTAG_TMS LOC="P107" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TMS
125 | #NET JTAG_TCK LOC="P109" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TCK
126 | #NET JTAG_TDI LOC="P110" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDI
127 | #NET JTAG_TDO LOC="P106" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDO
128 | #NET FLASH_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS
129 | #NET FLASH_CK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK
130 | #NET FLASH_SI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI
131 | #NET FLASH_SO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # FLASH_SO
132 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/pslib.py:
--------------------------------------------------------------------------------
1 | # Python code to generate Postscript
2 | # http://www.physics.emory.edu/~weeks/graphics/howtops1.html
3 | # http://mahi.ucsd.edu/shearer/COMPCLASS/post.txt
4 |
5 | import sys
6 |
7 |
8 | class Point:
9 | def __init__(self, x=0., y=0.):
10 | self.x = x
11 | self.y = y
12 |
13 | def __repr__(self):
14 | return '(%f, %f)' % (self.x, self.y)
15 |
16 | def transform(self, xfm):
17 | return Point(xfm.scale * (self.x + xfm.origin.x), xfm.scale * (self.y + xfm.origin.y))
18 |
19 | def moveto(self, stream):
20 | stream.write('%f %f moveto ' % (self.x, self.y))
21 |
22 | def lineto(self, stream):
23 | stream.write('%f %f lineto ' % (self.x, self.y))
24 |
25 | def __add__(self, other):
26 | return Point(self.x + other.x, self.y + other.y)
27 |
28 | def __sub__(self, other):
29 | return Point(self.x - other.x, self.y - other.y)
30 |
31 | def length(self):
32 | return (self.x * self.x + self.y * self.y) ** .5
33 |
34 | def dist(self, other):
35 | return (self - other).length()
36 |
37 | def __rmul__(self, other):
38 | if isinstance(other, Point):
39 | # dot product
40 | return self.x * other.x + self.y * other.y
41 | else:
42 | # scaling
43 | return Point(self.x * other, self.y * other)
44 |
45 | def parallel(self, other):
46 | # find the component of this 2-vector parallel to the arg 2-vector
47 | return ((self * other) / (other * other)) * other
48 |
49 | def perpendicular(self, other):
50 | # find the component of this 2-vector perpendicular to the arg 2-vector
51 | return self - self.parallel(other)
52 |
53 | def normal(self):
54 | return (1. / (self * self) ** .5) * self
55 |
56 | @classmethod
57 | def average(klas, *points):
58 | sum = klas()
59 | for p in points:
60 | sum = sum + p
61 | return (1. / len(points)) * sum
62 |
63 |
64 | class Transformation:
65 | def __init__(self, scale, origin):
66 | self.scale = scale
67 | self.origin = origin
68 |
69 | def rescale(self, x):
70 | return Transformation(x * self.scale, self.origin)
71 |
72 | def translate(self, offset):
73 | return Transformation(self.scale, self.origin + offset)
74 |
75 |
76 | class Path:
77 | def __init__(self, *points):
78 | self.points = points
79 |
80 | def __repr__(self):
81 | return '<' + self.__class__.__name__ + ' ' + repr(self.points) + '>'
82 |
83 | def transform(self, xfm):
84 | return apply(Path, tuple([p.transform(xfm) for p in self.points]))
85 |
86 | def render(self, stream):
87 | stream.write('newpath ')
88 | self.points[0].moveto(stream)
89 | for p in self.points[1:]:
90 | p.lineto(stream)
91 | stream.write('stroke\n')
92 |
93 |
94 | class Hole:
95 | def __init__(self, center, radius):
96 | self.center = center
97 | self.radius = radius
98 |
99 | def transform(self, xfm):
100 | return Hole(self.center.transform(xfm), xfm.scale * self.radius)
101 |
102 | def render(self, stream):
103 | stream.write('newpath ')
104 | stream.write('%f %f %f 0 360 arc stroke\n' % (self.center.x, self.center.y, self.radius))
105 |
106 |
107 | class Polygon(Path):
108 | def __init__(self, *points):
109 | self.points = list(points) + [points[0]]
110 |
111 |
112 | class PostscriptPage:
113 | def __init__(self):
114 | self.paths = []
115 |
116 | def transform(self, xfm):
117 | page = PostscriptPage()
118 | page.paths = [path.transform(xfm) for path in self.paths]
119 | return page
120 |
121 | def add_path(self, path):
122 | self.paths.append(path)
123 |
124 | def add_paths(self, *paths):
125 | [self.paths.append(path) for path in paths]
126 |
127 | def add_polygon(self, *points):
128 | self.paths.append(apply(Polygon, points))
129 |
130 | def render(self, stream=sys.stdout):
131 | # compute bounding box
132 | xmin = ymin = 1.e20
133 | xmax = ymax = -1.e20
134 | for path in self.paths:
135 | if isinstance(path, Path):
136 | for p in path.points:
137 | xmin = min(xmin, p.x)
138 | xmax = max(xmax, p.x)
139 | ymin = min(ymin, p.y)
140 | ymax = max(ymax, p.y)
141 | elif isinstance(path, Hole):
142 | x, y, r = path.center.x, path.center.y, path.radius
143 | xmin = min(xmin, x - r)
144 | xmax = max(xmax, x + r)
145 | ymin = min(ymin, y - r)
146 | ymax = max(ymax, y + r)
147 | stream.write('%!PS-Adobe-3.0 EPSF-3.0\n')
148 | # llx lly urx ury
149 | stream.write('%%BoundingBox: %f %f %f %f\n' % (xmin, ymin, xmax, ymax))
150 | [path.render(stream) for path in self.paths]
151 | stream.write('showpage\n')
152 |
153 |
154 | def sierpinski(p1, p2, p3, gap=0., depth=5, minsize=0.):
155 | if depth <= 0:
156 | return []
157 | if p1.dist(p2) < minsize and p1.dist(p3) < minsize and p2.dist(p3) < minsize:
158 | return []
159 | def edgepoint(u, v, w, gap=gap):
160 | h = 0.5 * gap * (w - u).perpendicular(v - u).normal()
161 | return Point.average(u, v) + h
162 | a, b, c = Point.average(p2, p3), Point.average(p1, p3), Point.average(p1, p2)
163 | return [
164 | Polygon(edgepoint(p1, p2, p3), edgepoint(p2, p3, p1), edgepoint(p3, p1, p2))
165 | ] + \
166 | sierpinski(p1, b, c, gap, depth-1, minsize) + \
167 | sierpinski(a, p2, c, gap, depth-1, minsize) + \
168 | sierpinski(a, b, p3, gap, depth-1, minsize)
169 |
170 |
171 |
172 | PS_SPACE = Transformation(72, Point()) # PS is 72 DPI
173 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/ramp.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 |
3 | module foo(
4 | clk,
5 | out_a,
6 | out_b,
7 | out_c,
8 | out_d
9 | );
10 |
11 | input clk;
12 | output out_a; // A0
13 | output out_b; // A1
14 | output out_c; // A2
15 | output out_d; // A3
16 | wire out_a;
17 | wire out_b;
18 | wire out_c;
19 | wire out_d;
20 |
21 | reg [9:0] fast_counter;
22 | reg [6:0] ramp_counter;
23 | reg [4:0] dac_counter;
24 | reg [14:0] dac_data;
25 | reg cs_active;
26 | wire clk_slow;
27 | assign clk_slow = fast_counter == 0;
28 | assign out_c = !clk;
29 | assign out_b = ((dac_data >> (13 - dac_counter)) & 1) && (dac_counter < 14);
30 | assign out_d = !cs_active;
31 | assign out_a = 0;
32 |
33 | always @(posedge clk) begin
34 |
35 | // the ramp is generated by counting up on each clk_slow tick
36 | // 7 bits => 31.25 kHz / (2**7) = 244-ish Hz, a little below middle C
37 | if (clk_slow) begin
38 | ramp_counter <= ramp_counter + 1;
39 | end
40 |
41 | // clk_slow is 32 MHz divided by 1024, or 31.25 kHz
42 | fast_counter <= fast_counter + 1;
43 |
44 | // on each clk_slow tick, send a sample to the serial 14-bit DAC
45 | if (clk_slow) begin
46 | dac_counter <= 0;
47 | cs_active <= 1;
48 | end else if (dac_counter < 16) begin
49 | if (dac_counter == 15) begin
50 | dac_data <= (ramp_counter << 6) + (1 << 12);
51 | cs_active <= 0;
52 | end
53 | dac_counter <= dac_counter + 1;
54 | end
55 | end
56 |
57 | endmodule
58 |
--------------------------------------------------------------------------------
/fpga-synth/instrument/simple_body.py:
--------------------------------------------------------------------------------
1 | # Simplified body, this is just two parallel triangles
2 |
3 | import pslib
4 |
5 | A = 24
6 | B = 16
7 |
8 | page = pslib.PostscriptPage()
9 |
10 | a = pslib.Point(0, 0)
11 | b = pslib.Point(B, 0)
12 | c = pslib.Point(B / 2, A)
13 | d = pslib.Point.average(a, b, c)
14 |
15 | page.add_polygon(a, b, c)
16 |
17 | h = 0.4
18 | a1 = h * a + (1 - h) * d
19 | b1 = h * b + (1 - h) * d
20 | c1 = h * c + (1 - h) * d
21 |
22 | def keyboard():
23 | holes = []
24 | m, n = 0.7, 0.375
25 | m, n = 0.7, 0.4
26 | for (a, blo, bhi) in ((0, 1, 7), (1, 0, 12), (2, 5, 17), (3, 10, 22), (4, 15, 21)):
27 | for b in range(blo, bhi):
28 | x = 14 + m * a - n * b
29 | y = 1.5 + m * b + n * a
30 | holes.append(pslib.Hole(pslib.Point(x, y), 0.1))
31 | return holes
32 |
33 | [page.add_path(h) for h in keyboard()]
34 |
35 | apply(page.add_paths, pslib.sierpinski(a1, b1, c1, depth=3, gap=0.4))
36 |
37 | # here's the back
38 | # a = pslib.Point(3 * B / 2, A)
39 | # page.add_polygon(a, b, c)
40 |
41 | # page.transform(pslib.PS_SPACE.rescale(0.35)).render()
42 | page.transform(pslib.PS_SPACE).render()
43 |
--------------------------------------------------------------------------------
/fpga-synth/output_stage.py:
--------------------------------------------------------------------------------
1 | import math
2 | import unittest
3 | import sys
4 |
5 | from myhdl import Signal, delay, Simulation, always_comb, \
6 | instance, intbv, bin, toVerilog, toVHDL, always, now, traceSignals
7 | from config import (
8 | MHZ,
9 | N,
10 | WHOLE,
11 | MASK,
12 | HALF,
13 | unsigned_bus,
14 | signed_bus,
15 | signed_to_unsigned,
16 | unsigned_to_signed
17 | )
18 |
19 | """
20 | Make A a 32-bit number. Make B 16 bits, and vc_estimate 16 bits. Then the sum of
21 | A+B*vc_estimate will be 32 bits, clipped to (1<<32)-1 and take
22 | the upper 16 bits for the next value of vc_estimate. Get dac_bit by comparing
23 | vc_estimate with (target << 2).
24 | """
25 |
26 | DT = 1./MHZ
27 | R = 1000
28 | C = 0.01e-6
29 | ALPHA = math.exp(-DT / (R * C))
30 | A = int(round((1. - ALPHA) * (1 << 32)))
31 | B = int(round(ALPHA * (1 << 16)))
32 |
33 |
34 | # fastclk is the 32 MHz clock to the FPGA
35 | # clk is the audio-rate clock at 40 kHz, which is high for one fastclk period
36 | def interpolator(fastclk, clk, reset, input_data, interp_out):
37 |
38 | # There are 800 fastclk periods during each clk period, so on each fastclk we want to
39 | # advance 1/800th from the previous sound sample to the current sample. 800 is pretty
40 | # close to (1<<22) divided by 5243, so we can compute a delta by multiplying the
41 | # difference between samples by 5243, which is easy because it's constant and not too
42 | # many non-zero bits. By accumulating this difference and right-shifting 22 bits, we
43 | # arrive almost exactly where we want to end up after 800 accumulations.
44 |
45 | FRACTION_BITS = 16
46 | delay_1 = signed_bus(N)
47 | x = signed_bus(N)
48 | interp_step = signed_bus(N + FRACTION_BITS)
49 | interp_data = signed_bus(N + FRACTION_BITS)
50 |
51 | @always(fastclk.posedge, reset.posedge)
52 | def do_stuff():
53 | if reset:
54 | delay_1.next = 0
55 | interp_data.next = 0
56 | interp_step.next = 0
57 | else:
58 | if clk:
59 | interp_data.next = delay_1 << FRACTION_BITS
60 | delay_1.next = input_data
61 | # multiply by 5243 in binary
62 | interp_step.next = (x << 12) + (x << 10) + (x << 6) + (x << 5) + \
63 | (x << 4) + (x << 3) + (x << 1) + x
64 | elif (interp_data + interp_step) < interp_data.min:
65 | interp_data.next = interp_data.min
66 | elif (interp_data + interp_step) >= interp_data.max:
67 | interp_data.next = interp_data.max - 1
68 | else:
69 | interp_data.next = interp_data + interp_step
70 |
71 | @always_comb
72 | def rightshift_for_output():
73 | x.next = input_data - delay_1
74 | interp_out.next = interp_data >> FRACTION_BITS
75 |
76 | return (do_stuff, rightshift_for_output)
77 |
78 |
79 | def delta_sigma_dac(fastclk, clk, reset, input_data, dac_bit):
80 |
81 | interp_result = signed_bus(N)
82 | interp_result_unsigned = unsigned_bus(N)
83 | # the input of the Xilinx multiplier is an 18-bit factor
84 | vc_estimate = unsigned_bus(16)
85 | # the output of the Xilinx multiplier is a 36-bit product
86 | sum_of_products = unsigned_bus(32)
87 | dac_bit_internal = Signal(False)
88 |
89 | @always_comb
90 | def drive_dac_bit():
91 | dac_bit.next = dac_bit_internal
92 |
93 | @always(fastclk.posedge, reset.posedge)
94 | def do_stuff():
95 | # sum_of_products is the next value for vc_estimate, with lots of fraction
96 | # bits. vc_estimate already has fraction bits beyond N. All these fraction
97 | # bits are helpful in keeping out audible artifacts.
98 | if reset:
99 | dac_bit_internal.next = 0
100 | vc_estimate.next = 1 << 15
101 | else:
102 | dac_bit_internal.next = interp_result_unsigned > (sum_of_products >> (32 - N))
103 | vc_estimate.next = sum_of_products >> 16
104 |
105 | @always_comb
106 | def multiply():
107 | if dac_bit_internal:
108 | if A + (B * vc_estimate) >= (1 << 32):
109 | sum_of_products.next = (1 << 32) - 1
110 | else:
111 | sum_of_products.next = A + (B * vc_estimate)
112 | else:
113 | sum_of_products.next = B * vc_estimate
114 |
115 | things = [
116 | # Interpolation is a huge help with anti-aliasing.
117 | interpolator(fastclk, clk, reset, input_data, interp_result),
118 | drive_dac_bit,
119 | do_stuff,
120 | multiply,
121 | signed_to_unsigned(N, interp_result, interp_result_unsigned)
122 | ]
123 | return things
124 |
125 | def make_dsig_ios():
126 | fastclk = Signal(False)
127 | clk = Signal(False)
128 | input_data = signed_bus(N)
129 | dac_bit = Signal(False)
130 | return (fastclk, clk, input_data, dac_bit)
131 |
132 |
133 | class TestOutputStage(unittest.TestCase):
134 | pass # TODO write some tests
135 |
136 |
137 | def simulate():
138 | fastclk, clk, input_data, dac_bit = make_dsig_ios()
139 | dsig = delta_sigma_dac(fastclk, clk, input_data, dac_bit)
140 |
141 | @instance
142 | def bench():
143 | fastclk.next = 0
144 | clk.next = 0
145 | input_data.next = 0
146 | yield delay(1)
147 | for j in range(100):
148 | for i in range(800):
149 | fastclk.next = 1
150 | yield delay(1)
151 | fastclk.next = 0
152 | yield delay(1)
153 | input_data.next = input_data + 50
154 | fastclk.next = 1
155 | clk.next = 1
156 | yield delay(1)
157 | fastclk.next = 0
158 | yield delay(1)
159 | clk.next = 0
160 |
161 | return (bench, dsig)
162 |
163 |
164 | if __name__ == '__main__':
165 | if 'hdl' in sys.argv[1:]:
166 | fastclk, clk, input_data, dac_bit = make_dsig_ios()
167 | toVerilog(dsig, fastclk, clk, input_data, dac_bit)
168 | elif 'sim' in sys.argv[1:]:
169 | Simulation(traceSignals(simulate)).run()
170 | else:
171 | suite = unittest.TestLoader().loadTestsFromTestCase(TestOutputStage)
172 | unittest.TextTestRunner(verbosity=2).run(suite)
173 |
--------------------------------------------------------------------------------
/fpga-synth/param_loading.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import math
3 | import sys
4 | from myhdl import Signal, delay, Simulation, always_comb, \
5 | instance, intbv, bin, toVerilog, toVHDL, always, now, traceSignals
6 |
7 | def get_nibbles(n):
8 | return [Signal(intbv(0)[4:]) for i in range(n)]
9 |
10 |
11 | def bitfields(source, *args):
12 | retval = []
13 |
14 | def make_f(source, offset, len, signal):
15 | @always_comb
16 | def f():
17 | signal.next = (source >> offset) & ((1 << len) - 1)
18 | return f
19 |
20 | for offset, len, signal in args:
21 | retval.append(make_f(source, offset, len, signal))
22 | return retval
23 |
24 | class DaisyChain:
25 |
26 | '''
27 | This works a bit like JTAG except that it's a four-bit-wide bus. There are two
28 | clocks, pclk and outclk. Pclk advances the nibbles along the daisy chain, and
29 | outclk clocks them all simultaneously to the output latches.
30 | '''
31 |
32 | @classmethod
33 | def set_up_clocks(cls, pclk, outclk):
34 | cls.pclk = pclk
35 | cls.outclk = outclk
36 |
37 | def __init__(self, pdata_in):
38 | self.pdata_in = pdata_in
39 |
40 | def _param_nibble(self, out, pdata_out):
41 | pdata_in = self.pdata_in
42 | self.pdata_in = pdata_out
43 | q = Signal(intbv(0)[4:])
44 | r = Signal(intbv(0)[4:])
45 |
46 | @always(self.pclk.posedge)
47 | def f():
48 | q.next = pdata_in
49 |
50 | @always(self.outclk.posedge)
51 | def g():
52 | r.next = q
53 |
54 | @always_comb
55 | def h():
56 | pdata_out.next = q
57 | out.next = r
58 |
59 | return (f, g, h)
60 |
61 | def param_8(self, out, pdata_out):
62 | a = Signal(intbv(0)[4:])
63 | b = Signal(intbv(0)[4:])
64 | q = Signal(intbv(0)[4:])
65 |
66 | nibble0 = self._param_nibble(a, q)
67 | nibble1 = self._param_nibble(b, pdata_out)
68 |
69 | @always_comb
70 | def f():
71 | out.next = (a << 4) | b
72 |
73 | return (f, nibble0, nibble1)
74 |
75 | def param_16(self, out, pdata_out, limit_bits=16):
76 | a = Signal(intbv(0)[8:])
77 | b = Signal(intbv(0)[8:])
78 | q = Signal(intbv(0)[4:])
79 | pa = self.param_8(a, q)
80 | pb = self.param_8(b, pdata_out)
81 |
82 | @always_comb
83 | def f():
84 | out.next = ((a << 8) | b) & ((1 << limit_bits) - 1)
85 |
86 | return (pa, pb, f)
87 |
88 | def param_24(self, out, pdata_out):
89 | a = Signal(intbv(0)[16:])
90 | b = Signal(intbv(0)[8:])
91 | q = Signal(intbv(0)[4:])
92 | pa = self.param_16(a, q)
93 | pb = self.param_8(b, pdata_out)
94 |
95 | @always_comb
96 | def f():
97 | out.next = (a << 8) | b
98 |
99 | return (pa, pb, f)
100 |
101 | def param_32(self, out, pdata_out):
102 | a = Signal(intbv(0)[16:])
103 | b = Signal(intbv(0)[16:])
104 | q = Signal(intbv(0)[4:])
105 | pa = self.param_16(a, q)
106 | pb = self.param_16(b, pdata_out)
107 |
108 | @always_comb
109 | def f():
110 | out.next = (a << 16) | b
111 |
112 | return (pa, pb, f)
113 |
114 |
115 | def param_clock_driver(byte_sequence, pclk, period):
116 |
117 | '''
118 | Helpful for writing tests.
119 | '''
120 |
121 | NUM_NIBBLES = len(byte_sequence) * 2
122 |
123 | @instance
124 | def clock_driver():
125 | for i in range(NUM_NIBBLES):
126 | pclk.next = 0
127 | yield delay(period / 2)
128 | pclk.next = 1
129 | yield delay(period / 2)
130 | pclk.next = 0 # 80
131 |
132 | return clock_driver
133 |
134 | def daisy_chain_driver(byte_sequence, pdata, outclk, period):
135 |
136 | '''
137 | Helpful for writing tests.
138 | '''
139 |
140 | @instance
141 | def pdata_driver():
142 | for x in byte_sequence:
143 | pdata.next = x & 0xF
144 | yield delay(period)
145 | pdata.next = (x >> 4) & 0xF
146 | yield delay(period)
147 | yield delay(period / 2)
148 | outclk.next = 1
149 | yield delay(period / 2)
150 | outclk.next = 0
151 | yield delay(2 * period)
152 | pdata.next = 0
153 |
154 | return pdata_driver
155 |
156 |
157 | ################
158 |
159 | def test_bench():
160 |
161 | # these are clock and input signals for the whole daisychain
162 | pclk = Signal(False)
163 | pdata = Signal(intbv(0)[4:])
164 | outclk = Signal(False)
165 | DaisyChain.set_up_clocks(pclk, outclk)
166 |
167 | # these are the parameters driven by the daisychain
168 | result1 = Signal(intbv(0)[8:])
169 | result2 = Signal(intbv(0)[24:])
170 | result3 = Signal(intbv(0)[32:])
171 |
172 | param_bytes = (
173 | 0x26, # result3, little-endian
174 | 0x59,
175 | 0x41,
176 | 0x31,
177 | 0x21, # result2, little-endian
178 | 0x43,
179 | 0x65,
180 | 0x87) # result 1
181 |
182 | # daisychain links
183 | a, b, c = get_nibbles(3)
184 | chain = DaisyChain(pdata)
185 |
186 | r = (
187 | chain.param_8(result1, a),
188 | chain.param_24(result2, b),
189 | chain.param_32(result3, c),
190 | param_clock_driver(param_bytes, pclk, 10),
191 | daisy_chain_driver(param_bytes, pdata, outclk, 10),
192 | )
193 | return r
194 |
195 | if __name__ == '__main__':
196 | Simulation(traceSignals(test_bench)).run()
197 |
--------------------------------------------------------------------------------
/fpga-synth/synth.py:
--------------------------------------------------------------------------------
1 | # MyHDL code for a Moog-style synth done in DSP on a Xilinx FPGA
2 |
3 | import unittest
4 | import sys
5 | from myhdl import Signal, delay, Simulation, always_comb, \
6 | instance, intbv, bin, toVerilog, toVHDL, always, now, traceSignals
7 |
8 | from wavegen import waveform_generator, make_wavgen_ios
9 | from param_loading import (
10 | get_nibbles,
11 | DaisyChain,
12 | bitfields,
13 | daisy_chain_driver,
14 | param_clock_driver
15 | )
16 | from output_stage import delta_sigma_dac
17 | from amps_filters import vca
18 | from envgen import adsr
19 | from config import (
20 | MHZ,
21 | AUDIO_RATE,
22 | DIVIDER,
23 | N,
24 | WHOLE,
25 | HALF,
26 | MASK,
27 | SECOND,
28 | compute_delta_phase,
29 | unsigned_bus,
30 | signed_bus,
31 | signed_to_unsigned,
32 | unsigned_to_signed
33 | )
34 |
35 |
36 | A_ABOVE_MIDDLE_C = compute_delta_phase(440)
37 | DELTA_PHASE = A_ABOVE_MIDDLE_C
38 |
39 |
40 | def make_fpga_ios():
41 | fastclk = Signal(False)
42 | reset = Signal(False)
43 | param_data = unsigned_bus(4)
44 | param_clk = Signal(False)
45 | audio_req = Signal(False)
46 | audio_ack = Signal(False)
47 | dac_bit = Signal(True)
48 | return (fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit)
49 |
50 |
51 | def fpga(fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit):
52 |
53 | aclk_counter = unsigned_bus(10)
54 | clk = Signal(False)
55 |
56 | # audio rate clock
57 | @always(fastclk.posedge, reset.posedge)
58 | def drive_audio_clock():
59 | if reset:
60 | aclk_counter.next = 0
61 | clk.next = True
62 | elif aclk_counter >= 800:
63 | aclk_counter.next = 0
64 | clk.next = True
65 | else:
66 | aclk_counter.next = aclk_counter + 1
67 | clk.next = False
68 |
69 | ignored, ignored2, select, threshold, delta_phase, wavgen_output = make_wavgen_ios()
70 |
71 | keydown = Signal(False)
72 | select = unsigned_bus(2)
73 | attack = unsigned_bus(4)
74 | decay = unsigned_bus(4)
75 | sustain = unsigned_bus(4)
76 | _release = unsigned_bus(4)
77 | amplitude = unsigned_bus(N)
78 | _output = signed_bus(N)
79 |
80 | # more bits than we really need, 18 bits would give 6.5536 seconds
81 | input_driver_count = unsigned_bus(24)
82 |
83 | @always(clk.posedge, reset.posedge)
84 | def drive_inputs():
85 | attack.next = 3
86 | decay.next = 5
87 | sustain.next = 8
88 | _release.next = 0
89 | delta_phase.next = DELTA_PHASE
90 | select.next = 1
91 | threshold.next = HALF
92 | keydown.next = 0
93 | if reset:
94 | keydown.next = 0
95 | input_driver_count.next = 0
96 | elif input_driver_count >= 5 * SECOND:
97 | keydown.next = 0
98 | input_driver_count.next = 0
99 | elif input_driver_count < 2 * SECOND:
100 | keydown.next = 1
101 | input_driver_count.next = input_driver_count + 1
102 | else:
103 | keydown.next = 0
104 | input_driver_count.next = input_driver_count + 1
105 |
106 | drivers = [
107 | drive_audio_clock,
108 | drive_inputs,
109 | waveform_generator(clk, reset, select, threshold, delta_phase, wavgen_output),
110 | # adsr(clk, reset, keydown, attack, decay, sustain, _release, amplitude),
111 | # vca(fastclk, reset, wavgen_output, amplitude, _output),
112 | delta_sigma_dac(fastclk, clk, reset, wavgen_output, dac_bit),
113 | ]
114 | return drivers
115 |
116 | def simulate():
117 |
118 | # don't make the simulation take all day
119 | global SECOND, DELTA_PHASE
120 | SECOND = 200
121 | DELTA_PHASE = compute_delta_phase(1000)
122 |
123 | fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit = make_fpga_ios()
124 |
125 | @instance
126 | def bench():
127 | fastclk.next = 0
128 | reset.next = 0
129 | param_data.next = 0
130 | param_clk.next = 0
131 | audio_req.next = 0
132 | audio_ack.next = 0
133 | yield delay(1)
134 | reset.next = 1
135 | yield delay(1)
136 | reset.next = 0
137 | # for i in range(8 * SECOND * 32000000 / 40000):
138 | for i in range(SECOND * 32000000 / 40000):
139 | yield delay(1)
140 | fastclk.next = 1
141 | yield delay(1)
142 | fastclk.next = 0
143 |
144 | stuff = [
145 | bench,
146 | fpga(fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit)
147 | ]
148 | return stuff
149 |
150 |
151 | class TestFpga(unittest.TestCase):
152 | # TODO write tests
153 | pass
154 |
155 |
156 | if __name__ == '__main__':
157 | if 'hdl' in sys.argv[1:]:
158 | fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit = make_fpga_ios()
159 | toVerilog(fpga, fastclk, reset, param_data, param_clk, audio_req, audio_ack, dac_bit)
160 | elif 'sim' in sys.argv[1:]:
161 | Simulation(traceSignals(simulate)).run()
162 | else:
163 | suite = unittest.TestLoader().loadTestsFromTestCase(TestFpga)
164 | unittest.TextTestRunner(verbosity=2).run(suite)
165 |
--------------------------------------------------------------------------------
/fpga-synth/tb_fpga.tf:
--------------------------------------------------------------------------------
1 | module tb_fpga;
2 |
3 | reg fastclk;
4 | reg reset;
5 | reg [3:0] param_data;
6 | reg param_clk;
7 | reg audio_req;
8 | reg audio_ack;
9 | wire dac_bit;
10 |
11 | initial begin
12 | fastclk <= 0;
13 | reset <= 0;
14 | param_data <= 0;
15 | param_clk <= 0;
16 | audio_req <= 0;
17 | audio_ack <= 0;
18 | #10 reset <= 1;
19 | #50 reset <= 0;
20 | #20 repeat (2500000) begin
21 | #25 fastclk <= 1;
22 | #25 fastclk <= 0;
23 | end
24 | end
25 |
26 | fpga dut(
27 | fastclk,
28 | reset,
29 | param_data,
30 | param_clk,
31 | audio_req,
32 | audio_ack,
33 | dac_bit
34 | );
35 |
36 | endmodule
37 |
--------------------------------------------------------------------------------
/fpga-synth/wavegen.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import sys
3 | from myhdl import Signal, delay, Simulation, always_comb, \
4 | instance, intbv, bin, toVerilog, toVHDL, always, now, traceSignals
5 | from config import (
6 | PHASEWIDTH,
7 | N,
8 | HALF,
9 | MASK,
10 | RAMP,
11 | TRIANGLE,
12 | SQWAVE,
13 | NOISE,
14 | unsigned_bus,
15 | signed_bus
16 | )
17 | from math import log
18 |
19 | def log2(x):
20 | if x < 0:
21 | return (False, log(-1.0 * x) / log(2.0))
22 | else:
23 | return (True, log(1.0 * x) / log(2.0))
24 |
25 | # Ramp wave, triangle wave, PW-modulated square wave, or noise
26 | # Clock this at the 40 kHz audio rate
27 | def waveform_generator(clk, reset, select, threshold, delta_phase, _output):
28 |
29 | NOISEWIDTH16 = 16 # depends on polynomial
30 | NOISEWIDTH13 = 13
31 | HALFPHASE = 1 << (PHASEWIDTH - 1)
32 | QUARTERPHASE = 1 << (PHASEWIDTH - 2)
33 | THREEQUARTERPHASE = HALFPHASE + QUARTERPHASE
34 | TRIANGLESHIFT = (PHASEWIDTH - N) - 1
35 | RAMPSHIFT = PHASEWIDTH - N
36 |
37 | phase_counter = unsigned_bus(PHASEWIDTH)
38 | noise_register_16 = unsigned_bus(NOISEWIDTH16)
39 | noise_register_13 = unsigned_bus(NOISEWIDTH13)
40 |
41 | @always(clk.posedge, reset.posedge)
42 | def waveforms():
43 | if reset:
44 | noise_register_16.next = 123
45 | noise_register_13.next = 1787
46 | phase_counter.next = 0
47 | _output.next = 0
48 | else:
49 | if noise_register_16 == 0:
50 | noise_register_16.next = 123
51 | elif (noise_register_16 ^ (noise_register_16 >> 2) ^
52 | (noise_register_16 >> 3) ^ (noise_register_16 >> 5)) & 1:
53 | noise_register_16.next = (1 << 15) + (noise_register_16 >> 1)
54 | else:
55 | noise_register_16.next = (noise_register_16 >> 1)
56 |
57 | if noise_register_13 == 0:
58 | noise_register_13.next = 1787
59 | elif (noise_register_13 ^ (noise_register_13 >> 1) ^
60 | (noise_register_13 >> 2) ^ (noise_register_13 >> 5)) & 1:
61 | noise_register_13.next = (1 << 12) + (noise_register_13 >> 1)
62 | else:
63 | noise_register_13.next = (noise_register_13 >> 1)
64 |
65 | if phase_counter + delta_phase >= (1 << PHASEWIDTH):
66 | phase_counter.next = phase_counter + delta_phase - (1 << PHASEWIDTH)
67 | else:
68 | phase_counter.next = phase_counter + delta_phase
69 |
70 | if select == RAMP:
71 | _output.next = (phase_counter - HALFPHASE) >> RAMPSHIFT
72 | elif select == TRIANGLE:
73 | if phase_counter < HALFPHASE:
74 | _output.next = (phase_counter - QUARTERPHASE) >> TRIANGLESHIFT
75 | else:
76 | _output.next = \
77 | (THREEQUARTERPHASE - phase_counter) >> TRIANGLESHIFT
78 | elif select == SQWAVE:
79 | if phase_counter > (threshold << (PHASEWIDTH - N)):
80 | _output.next = MASK - HALF
81 | else:
82 | _output.next = -HALF
83 | else: # NOISE
84 | _output.next = \
85 | ((noise_register_16 ^ noise_register_13) & MASK) - HALF
86 |
87 | return waveforms
88 |
89 | def make_wavgen_ios():
90 | clk = Signal(False)
91 | reset = Signal(False)
92 | select = unsigned_bus(2)
93 | threshold = unsigned_bus(N)
94 | delta_phase = unsigned_bus(PHASEWIDTH)
95 | _output = signed_bus(N)
96 | return (clk, reset, select, threshold, delta_phase, _output)
97 |
98 |
99 | class TestWaveformGenerator(unittest.TestCase):
100 |
101 | def test_ramp(self):
102 | pass
103 |
104 | def test_triangle(self):
105 | pass
106 |
107 | def test_square_wave(self):
108 | pass
109 |
110 | def test_noise(self):
111 | pass
112 |
113 |
114 | def simulate():
115 | from config import DELTA_PHASE
116 | clk, reset, select, threshold, delta_phase, _output = make_wavgen_ios()
117 | wavgen = waveform_generator(clk, reset, select, threshold, delta_phase, _output)
118 |
119 | @instance
120 | def bench():
121 | clk.next = 0
122 | yield delay(1)
123 | reset.next = 1
124 | yield delay(1)
125 | reset.next = 0
126 | select.next = RAMP
127 | delta_phase.next = DELTA_PHASE
128 | threshold.next = HALF
129 | for i in range(1000):
130 | yield delay(1)
131 | clk.next = 1
132 | yield delay(1)
133 | clk.next = 0
134 | select.next = TRIANGLE
135 | for i in range(1000):
136 | yield delay(1)
137 | clk.next = 1
138 | yield delay(1)
139 | clk.next = 0
140 | select.next = SQWAVE
141 | for i in range(1000):
142 | yield delay(1)
143 | clk.next = 1
144 | yield delay(1)
145 | clk.next = 0
146 | select.next = NOISE
147 | for i in range(1000):
148 | yield delay(1)
149 | clk.next = 1
150 | yield delay(1)
151 | clk.next = 0
152 |
153 | return (bench, wavgen)
154 |
155 |
156 | if __name__ == '__main__':
157 | if 'hdl' in sys.argv[1:]:
158 | clk, reset, select, threshold, delta_phase, _output = make_wavgen_ios()
159 | toVerilog(waveform_generator, clk, reset, select, threshold, delta_phase, _output)
160 | elif 'sim' in sys.argv[1:]:
161 | Simulation(traceSignals(simulate)).run()
162 | else:
163 | suite = unittest.TestLoader().loadTestsFromTestCase(TestEnvelopeGenerator)
164 | unittest.TextTestRunner(verbosity=2).run(suite)
165 |
--------------------------------------------------------------------------------