generated from TinyTapeout/tt05-verilog-demo
-
Notifications
You must be signed in to change notification settings - Fork 1
/
info.yaml
358 lines (281 loc) · 20.3 KB
/
info.yaml
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
---
# Tiny Tapeout project information
project:
wokwi_id: 0 # If using wokwi, set this to your project's ID
# If using an HDL, set wokwi_id as 0 and uncomment and list your source files here.
# Source files must be in ./src and you must list each source file separately
source_files:
- attenuation.v
- tone.v
- noise.v
- envelope.v
- signal_edge.v
- pwm.v
- tt_um_rejunity_ay8913.v
top_module: "tt_um_rejunity_ay8913" # Put the name of your top module here, must start with "tt_um_". Make it unique by including your github username
# How many tiles your design occupies? A single tile is about 167x108 uM.
tiles: "1x1" # Valid values: 1x1, 1x2, 2x2, 4x2 or 8x2
# Keep a track of the submission yaml
yaml_version: 4
# As everyone will have access to all designs, try to make it easy for someone new to your design to know what
# it does and how to operate it. This info will be automatically collected and used to make a datasheet for the chip.
documentation:
author: "ReJ aka Renaldas Zioma"
title: "Classic 8-bit era Programmable Sound Generator AY-3-8913"
language: "Verilog"
description: "The AY-3-8913 is a 3-voice programmable sound generator (PSG) chip from General Instruments. The AY-3-8913 is a smaller variant of AY-3-8910 or its analog YM2149."
# Longer description of how the project works. You can use standard markdown format.
how_it_works: |
This Verilog implementation is a replica of the classical **[AY-3-8913](https://en.wikipedia.org/wiki/General_Instrument_AY-3-8910)** programmable sound generator.
With roughly a 1500 logic gates this design fits on a **single tile** of the TinyTapeout.
**The goals of this project**
1. closely replicate the behavior and eventually the complete **design of the original** AY-3-891x with builtin DACs
2. provide a readable and well documented code for educational and hardware **preservation** purposes
3. leverage the **modern fabrication** process
A significant effort was put into a thorough **test suite** for regression testing and validation against the original chip behavior.
**Chip technical capabilities**
- **3 square wave** tone generators
- A single **white noise** generator
- A single **envelope** generator able to produce 10 different shapes
- Chip is capable to produce a range of waves from a **30 Hz** to **125 kHz**, defined by **12-bit** registers.
- **16** different volume levels
___Registers___ The behavior of the AY-3-891x is defined by 14 registers.
| Register| Bits used | Function | Description |
|---------|----------------|------------------|------------------------|
| 0 | ```xxxxxxxx``` | Channel A Tone | 8-bit fine frequency |
| 1 | ```....xxxx``` | ---//--- | 4-bit coarse frequency |
| 2 | ```xxxxxxxx``` | Channel B Tone | 8-bit fine frequency |
| 3 | ```....xxxx``` | ---//--- | 4-bit coarse frequency |
| 4 | ```xxxxxxxx``` | Channel C Tone | 8-bit fine frequency |
| 5 | ```....xxxx``` | ---//--- | 4-bit coarse frequency |
| 6 | ```...xxxxx``` | Noise | 5-bit noise frequency |
| 7 | ```..CBACBA``` | Mixer | Tone and/or Noise per channel |
| 8 | ```...xxxxx``` | Channel A Volume | Envelope enable or 4-bit amplitude |
| 9 | ```...xxxxx``` | Channel B Volume | Envelope enable or 4-bit amplitude |
| 10 | ```...xxxxx``` | Channel C Volume | Envelope enable or 4-bit amplitude |
| 11 | ```xxxxxxxx``` | Envelope | 8-bit fine frequency |
| 12 | ```xxxxxxxx``` | ---//--- | 8-bit coarse frequency |
| 13 | ```....xxxx``` | Envelope Shape | 4-bit shape control |
___Square wave tone generators___ Square waves are produced by counting down the 12-bit counters. Counter counts up from 0. Once the corresponsding register value is reached, counter is reset and
the output bit of the channel is flipped producing square waves.
___Noise generator___ Noise is produced with 17-bit [Linear-feedback Shift Register (LFSR)](https://en.wikipedia.org/wiki/Linear-feedback_shift_register) that flips the output bit pseudo randomly.
The shift rate of the LFSR register is controller by the 5-bit counter.
___Envelope___ The envelope shape is controlled with 4-bit register, but can take only 10 distinct patterns. The speed of the envelope is controlled with 16-bit counter. Only a single envelope is produced that can be shared by any combination of the channels.
___Volume___ Each of the three AY-3-891x channels have dedicated DAC that converts 16 levels of volume to analog output. Volume levels are 3 dB apart in AY-3-891x.
**Historical use of the AY-3-891x**
The AY-3-891x family of programmable sound generators was introduced by General Instrument in 1978.
Soon Yamaha Corporation licensed and released a very similar chip under YM2149 name.
Both variants of the AY-3-891x and YM2149 were broadly used in home computers, game consoles and arcade machines in the early 80ies.
- home computers: Apple II [Mockingboard](https://en.wikipedia.org/wiki/Mockingboard) sound card, [Amstrad CPC](https://en.wikipedia.org/wiki/Amstrad_CPC), [Atari ST](https://en.wikipedia.org/wiki/Atari_ST), [Oric-1](https://en.wikipedia.org/wiki/Oric), [Sharp X1](https://en.wikipedia.org/wiki/Sharp_X1), [MSX](https://en.wikipedia.org/wiki/MSX), [ZX Spectrum 128/+2/+3](https://en.wikipedia.org/wiki/ZX_Spectrum)
- game consoles: [Intellivision](https://en.wikipedia.org/wiki/Intellivision), [Vectrex](https://en.wikipedia.org/wiki/Vectrex), [Amstrad GX4000](https://en.wikipedia.org/wiki/Amstrad_GX4000)
- arcade machines: [Frogger, 1942, Spy Hunter](https://www.vgmpf.com/Wiki/index.php/AY-3-8910#Games) and etc.
The AY-3-891x chip family competed with the similar [Texas Instruments SN76489](https://en.wikipedia.org/wiki/Texas_Instruments_SN76489).
**The original pinout of the AY-3-8913**
The **AY-3-8913** was a 24-pin package release of the AY-3-8910 with a number of internal pins left simply unconnected.
The goal of AY-3-8913 was to reduce complexity for the designer and reduce the foot print on the PCB.
Otherwise the functionality of the chip is identical to AY-3-8910 and AY-3-8912.
```
,--._.--.
GND ---|1 24|<-- /cs*
BDIR -->|2 23|<-- a8*
BC1 -->|3 22|<-- /a9*
DA7 <->|4 21|<-- /RESET
DA6 <->|5 20|<-- CLOCK
DA5 <->|6 19|--- GND
DA4 <->|7 18|--> CHANNEL C OUT
DA3 <->|8 17|--> CHANNEL A OUT
DA2 <->|9 16| not connected
DA1 <->|10 15|--> CHANNEL B OUT
DA0 <->|11 14|<-- test*
test* <--|12 13|<-- VCC
`-------'
* -- omitted from this Verilog implementation
```
**Difference from the original hardware**
This Verilog implementation is a completely digital and synchronous design that differs from the original AY-3-8913
design which incorporated internal DACs and analog outputs.
___Audio signal output___ While the original chip had no summation
The module provides two alternative outputs for the generated audio signal:
1. digital 8-bit audio output suitable for external Digital to Analog Converter (DAC)
2. pseudo analog output through Pulse Width Modulation (PWM)
___Master output channel___ In contrast to the original chip which had only separate channel outputs, this implementation also provides
an optional summation of the channels into a single master output.
___No DC offset___ This implementation produces output 0/1 waveforms without DC offset.
___No /A8, A9 and /CS pins___ The combination of **/A8**, **A9** and **/CS** pins orginially were intended to select a specific sound chip out the larger array of devices connected to the same bus.
In this implementation this mechanism is omitted for simplicity, **/A8**, **A9** and **/CS** are considered to be tied **low** and chip behaves as always enabled.
___Synchronous reset and single phase clock___ The original design employed 2 phases of the clock and asynchronous reset mechanism for operation of the registers.
To make it easier to synthesize and test on FPGAs this implementation uses single clock phase and synchronous reset for registers.
**The reverse engineered AY-3-891x**
This implementation would not be possible without the reverse engineered [schematics and analysis](https://github.com/lvd2/ay-3-8910_reverse_engineered)
based on decapped [AY-3-8910](https://siliconpr0n.org/map/gi/ay-3-8910) and [AY-3-8914](https://siliconpr0n.org/map/gi/ay-3-8914) chips.
# Instructions on how someone could test your project, include things like what buttons do what and how to set the clock if needed
how_to_test: |
The data bus of the AY-3-8913 chip has to be connected to microcontroller and receive a regular stream of commands.
The AY-3-8913 produces audio output and has to be connected to a speaker. There are several ways how the overall schematics can be established.
___8-bit parallel output via DAC___ One option is to connect off the shelf data parallel Digital to Analog Converter (DAC)
for example [Digilent R2R Pmod](https://digilent.com/reference/pmod/pmodr2r/start) to the output pins and
route the resulting analog audio to piezo speaker or amplifier.
```
uController AY-3-8913
,---------. ,---._.---.
| | 2 Mhz ->|CLK SEL0|<-- 0
| GPIOx|----------->|BC1 SEL1|<-- 0
| GPIOx|----------->|BDI | ,----------.
| GPIOx|----------->|DA0 OUT0|-------->|LSB |
| GPIOx|----------->|DA1 OUT1|-------->| |
| GPIOx|----------->|DA2 OUT2|-------->| pDAC | Headphones
| GPIOx|----------->|DA3 OUT3|-------->| or | or
| GPIOx|----------->|DA4 OUT4|-------->| RESISTOR | Buzzer
| GPIOx|----------->|DA5 OUT5|-------->| ladder | /|
| GPIOx|----------->|DA6 OUT6|-------->| | .--/ |
| GPIOx|----------->|DA7 OUT7|-------->|MSB |-----| |
`---------' `---------' `----------' `--` |
| `|
|
GND ---
```
___AUDIO OUT through RC filter___ Another option is to use the Pulse Width Modulated (PWM) AUDIO OUT pin that combines 4 channels with the Resistor-Capacitor based low-pass filter or better the Operation Amplifier (Op-amp) & Capacitor based integrator:
```
uController AY-3-8913
,---------. ,---._.---.
| | 2 Mhz ->|CLK SEL0|<-- 0
| GPIOx|----------->|BC1 SEL1|<-- 0
| GPIOx|----------->|BDIR |
| GPIOx|----------->|DA0 |
| GPIOx|----------->|DA1 |
| GPIOx|----------->|DA2 | C1
| GPIOx|----------->|DA3 | ,----||----.
| GPIOx|----------->|DA4 | | |
| GPIOx|----------->|DA5 | | Op-amp | Speaker
| GPIOx|----------->|DA6 AUDIO| | |X | /|
| GPIOx|----------->|DA7 OUT |-----+---|-X | C2 .--/ |
`---------' `---------' | }---+---||---| |
,--|+/ `--` |
| |/ | `|
| |
GND --- GND ---
```
___Separate channels through the Op-amp___ The third option is to externally combine 4 channels with the Operational Amplifier and low-pass filter:
```
uController AY-3-8913
,---------. ,---._.---.
| | 2 Mhz ->|CLK SEL0|<-- 0
| GPIOx|----------->|BC1 SEL1|<-- 0
| GPIOx|----------->|BDIR |
| GPIOx|----------->|DA0 |
| GPIOx|----------->|DA1 |
| GPIOx|----------->|DA2 | C1
| GPIOx|----------->|DA3 | ,----||----.
| GPIOx|----------->|DA4 | | |
| GPIOx|----------->|DA5 A|---. | Op-amp | Speaker
| GPIOx|----------->|DA6 B|---+ | |X | /|
| GPIOx|----------->|DA7 C|---+--+---|-X | C2 .--/ |
`---------' `---------' | }---+---||---| |
,--|+/ `--` |
| |/ | `|
| |
GND --- GND ---
```
**Summary of commands to communicate with the chip**
The AY-3-8913 is programmed by updating its internal registers via the data bus. Below is a short summary of the communication protocol of AY-3-891x. Please consult [AY-3-891x Technical Manual](https://github.com/rejunity/tt05-psg-ay8913/blob/main/docs/AY-3-8910_Manual.pdf) for more information.
| BDIR | BC1 | Bus state description |
|------|-----|------------------------------------------------------|
| 0 | 0 | Bus is inactive |
| 0 | 1 | (Not implemented) |
| 1 | 0 | Write bus value to the previously latched register # |
| 1 | 1 | Latch bus value as the destination register # |
___Latch register address___ First, put the destination register adress on the bus of the chip and latch it by
pulling both **BDIR** and **BC1** pins **high**.
___Write data to register___ Put the desired value on the bus of the chip. Pull **BC1** pin **low** while keeping **BDIR** pin **high** to
write the value of the bus to the latched register address.
___Inactivate bus___ by pulling both **BDIR** and **BC1** pins **low**.
| Register | Format | Description | Parameters |
|---------|------------|--------------------------|-----------------|
| 0,2,4 | `ffffffff` | A/B/C tone period | `f` - low bits |
| 1,3,5 | `0000FFFF` | ---//--- | `F` - high bits |
| 6 | `000fffff` | Noise period | `f` - noise period |
| 7 | `00CBAcba` | Noise / tone per channel | `CBA` - noise off, |
| | | | `cba` - tone off |
| 8,9,10 | `000Evvvv` | A/B/C volume | `E` - envelope on, |
| | | | `v` - volume level |
| 11 | `ffffffff` | Envelope period | `f` - low bits |
| 12 | `FFFFFFFF` | ---//--- | `F` - high bits |
| 13 | `0000caAh` | Envelope Shape | `c` - continue, `a` - attack, `A` - alternate, `h` - hold |
**Note frequency**
Use the following formula to calculate the 12-bit period value for a particular note:
$$ tone period_{cycles} = clock_{frequency} / (16_{cycles} * note_{frequency}) $$
For example 12-bit period that plays 440 Hz note on a chip clocked at 2 MHz would be:
$$ tone period_{cycles} = 2000000 Hz / (16_{cycles} * 440 Hz) = 284 = 11C_{hex} $$
**An example to play a note at a maximum volume**
|BDIR|BC1| DA7..DA0 | Explanation |
|----|---|-----------|----------------------------------------------------------|
| 1 | 1 | `xxxx0000`| **Latch** tone A coarse register address $0 = 0000_{bin}$ |
| 1 | 0 | `xxxx0001`| **Write** high 4-bits of the 440 Hz note $1 = 0001_{bin}$ |
| 1 | 1 | `xxxx0001`| **Latch** tone A fine register address $1_{dec} = 0001_{bin}$ |
| 1 | 0 | `00011100`| **Write** low 8-bits of the note $1C_{hex} = 00011100_{bin}$ |
| 1 | 1 | `xxxx1000`| **Latch** channel A volume register address $8 = 1000_{bin}$ |
| 1 | 0 | `xxx01111`| **Write** maximum volume level $15_{dec} = 1111_{bin}$ with the envelope disabled |
```
Timing diagram
CLK ____ ____ ____ ____ ____ ____
__/ `____/ `____/ `____/ `____/ `____/ `____ ...
| | | | | |
| | | | | |
BDIR ______ ______ ______ ______ ______ ______
_/ `__/ `__/ `__/ `__/ `__/ `__
BC1 _______ _______ ________
_/ `___________/ `__________/ `___________
DA7..DA0_____ ________ ________ ________ ________ ________
_/ 0000 `/xxxx0001`/ 0001 `/00011100`/ 1000 `/xxx01111`
latch write latch write latch
```
**Externally configurable clock divider**
| SEL1 | SEL0 | Description | Clock frequency|
|------|------|------------------------------------|----------------|
| 0 | 0 | Standard mode, clock divided by 8 | 1.7 .. 2.0 MHz |
| 1 | 1 | -----//----- | 1.7 .. 2.0 MHz |
| 0 | 1 | New mode for TT05, no clock divider| 250 .. 500 kHZ |
| 1 | 0 | New mode for TT05, clock div. 128 | 25 .. 50 MHz |
| SEL1 | SEL0 | Formula to calculate the 12-bit tone period value for a note |
|------|------|--------------------------------------------------------------|
| 0 | 0 | $clock_{frequency} / (16_{cycles} * note_{frequency})$ |
| 1 | 1 | -----//----- |
| 0 | 1 | $clock_{frequency} / (2_{cycles} * note_{frequency})$ |
| 1 | 0 | $clock_{frequency} / (128_{cycles} * note_{frequency})$ |
# A description of what the inputs do (e.g. red button, SPI CLK, SPI MOSI, etc).
inputs:
- DA0 - multiplexed data/address bus
- DA1 - multiplexed data/address bus
- DA2 - multiplexed data/address bus
- DA3 - multiplexed data/address bus
- DA4 - multiplexed data/address bus
- DA5 - multiplexed data/address bus
- DA6 - multiplexed data/address bus
- DA7 - multiplexed data/address bus
# A description of what the outputs do
outputs:
- audio out (pwm)
- digita audio least significant bit
- digita audio
- digita audio
- digita audio
- digita audio
- digita audio
- digita audio most significant bit
# A description of what the bidirectional I/O pins do
bidirectional:
- (in) **BC1** bus control
- (in) **BDIR** bus direction
- (in) **SEL0** clock divider
- (in) **SEL1** clock divider
- (out) channel A (PWM)
- (out) channel B (PWM)
- (out) channel C (PWM)
- (out) AUDIO OUT master (PWM)
# The following fields are optional
tag: "psg, music, sound" # comma separated list of tags: test, encryption, experiment, clock, animation, utility, industrial, pwm, fpga, alu, microprocessor, risc, riscv, sensor, signal generator, fft, filter, music, bcd, sound, serial, timer, random number generator, calculator, decoder, counter, puzzle, multiplier, game, oscillator,
external_hw: "DAC (for ex. Digilent R2R PMOD), RC filter, amplifier, speaker" # Describe any external hardware needed
discord: "rzioma" # Your discord handle, used for communication and automatically assigning tapeout role after a submission
doc_link: "README.md" # URL to longer form documentation, eg the README.md in your repository
clock_hz: 2000000 # Clock frequency in Hz (if required)
picture: "docs/AY-3-8913.jpg" # relative path to a picture in your repository (must be 512kb or less)