OpenCores
URL https://opencores.org/ocsvn/psg16/psg16/trunk

Subversion Repositories psg16

[/] [psg16/] [trunk/] [rtl/] [verilog/] [PSGEnvGen.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
/* ============================================================================
2
    (C) 2007  Robert Finch
3
        All rights reserved.
4
 
5
        PSGEnvGen.v
6
        Version 1.1
7
 
8
        ADSR envelope generator.
9
 
10
    This source code is available for evaluation and validation purposes
11
    only. This copyright statement and disclaimer must remain present in
12
    the file.
13
 
14
 
15
        NO WARRANTY.
16
    THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER
17
    EXPRESS OR IMPLIED. The user must assume the entire risk of using the
18
    Work.
19
 
20
    IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
21
    INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO
22
    THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR.
23
 
24
    IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK
25
    IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN
26
    REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN
27
    LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU
28
    AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR
29
    LOSSES RELATING TO SUCH UNAUTHORIZED USE.
30
 
31
 
32
    Note that this envelope generator directly uses the values for attack,
33
    decay, sustain, and release. The original SID had to use four bit codes
34
    and lookup tables due to register limitations. This generator is
35
        built assuming there aren't any such register limitations.
36
        A wrapper could be built to provide that functionality.
37
 
38
    This component isn't really meant to be used in isolation. It is
39
    intended to be integrated into a larger audio component (eg SID
40
    emulator). The host component should take care of wrapping the control
41
    signals into a register array.
42
 
43
    The 'cnt' signal acts a prescaler used to determine the base frequency
44
    used to generate envelopes. The core expects to be driven at
45
    approximately a 1.0MHz rate for proper envelope generation. This is
46
    accomplished using the 'cnt' signal, which should the output of a
47
    counter used to divide the master clock frequency down to approximately
48
    a 1MHz rate. Therefore, the master clock frequency must be at least 4MHz
49
    for a 4 channel generator, 8MHZ for an 8 channel generator. The test
50
    system uses a 66.667MHz master clock and 'cnt' is the output of a seven
51
    bit counter that divides by 66.
52
 
53
    Note the resource space optimization. Rather than simply build a single
54
    channel ADSR envelope generator and instantiate it four or eight times,
55
    This unit uses a single envelope generator and time-multiplexes the
56
    controls from four (or eight) different channels. The ADSR is just
57
        complex enough that it's less expensive resource wise to multiplex the
58
        control signals. The luxury of time division multiplexing can be used
59
        here since audio signals are low frequency. The time division multiplex
60
        means that we need a clock that's four (or eight) times faster than
61
        would be needed if independent ADSR's were used. This probably isn't a
62
        problem for most cases.
63
 
64
        Spartan3
65
        Webpack 9.1i xc3s1000-4ft256
66
        522 LUTs / 271 slices / 81.155 MHz (speed)
67
============================================================================ */
68
 
69
/*
70
        sample attack values / rates
71
        ----------------------------
72
        8               2ms
73
        32              8ms
74
        64              16ms
75
        96              24ms
76
        152             38ms
77
        224             56ms
78
        272             68ms
79
        320             80ms
80
        400             100ms
81
        955             239ms
82
        1998    500ms
83
        3196    800ms
84
        3995    1s
85
        12784   3.2s
86
        21174   5.3s
87
        31960   8s
88
 
89
        rate = 990.00ns x 256 x value
90
*/
91
 
92
 
93
// envelope generator states
94
`define ENV_IDLE        0
95
`define ENV_ATTACK      1
96
`define ENV_DECAY       2
97
`define ENV_SUSTAIN     3
98
`define ENV_RELEASE     4
99
 
100
// Envelope generator
101
module PSGEnvGen(rst, clk, cnt,
102
        gate,
103
        attack0, attack1, attack2, attack3,
104
        decay0, decay1, decay2, decay3,
105
        sustain0, sustain1, sustain2, sustain3,
106
        relese0, relese1, relese2, relese3,
107
        o);
108
        parameter pChannels = 4;
109
        parameter pPrescalerBits = 8;
110
        input rst;                                                      // reset
111
        input clk;                                                      // core clock
112
        input [pPrescalerBits-1:0] cnt;          // clock rate prescaler
113
        input [15:0] attack0;
114
        input [15:0] attack1;
115
        input [15:0] attack2;
116
        input [15:0] attack3;
117
        input [11:0] decay0;
118
        input [11:0] decay1;
119
        input [11:0] decay2;
120
        input [11:0] decay3;
121
        input [7:0] sustain0;
122
        input [7:0] sustain1;
123
        input [7:0] sustain2;
124
        input [7:0] sustain3;
125
        input [11:0] relese0;
126
        input [11:0] relese1;
127
        input [11:0] relese2;
128
        input [11:0] relese3;
129
        input [3:0] gate;
130
        output [7:0] o;
131
 
132
        reg [7:0] sustain;
133
        reg [15:0] attack;
134
        reg [17:0] decay;
135
        reg [17:0] relese;
136
        // Per channel count storage
137
        reg [7:0] envCtr [3:0];
138
        reg [7:0] envCtr2 [3:0];
139
        reg [7:0] iv [3:0];                       // interval value for decay/release
140
        reg [2:0] icnt [3:0];             // interval count
141
        reg [19:0] envDvn [3:0];
142
        reg [2:0] envState [3:0];
143
 
144
        reg [2:0] envStateNxt;
145
        reg [15:0] envStepPeriod;        // determines the length of one step of the envelope generator
146
        reg [7:0] envCtrx;
147
        reg [19:0] envDvnx;
148
 
149
        // Time multiplexed values
150
        wire [15:0] attack_x;
151
        wire [11:0] decay_x;
152
        wire [7:0] sustain_x;
153
        wire [11:0] relese_x;
154
 
155
        integer n;
156
 
157
    wire [1:0] sel = cnt[1:0];
158
 
159
        mux4to1 #(16) u1 (
160
                .e(1'b1),
161
                .s(sel),
162
                .i0(attack0),
163
                .i1(attack1),
164
                .i2(attack2),
165
                .i3(attack3),
166
                .z(attack_x)
167
        );
168
 
169
        mux4to1 #(12) u2 (
170
                .e(1'b1),
171
                .s(sel),
172
                .i0(decay0),
173
                .i1(decay1),
174
                .i2(decay2),
175
                .i3(decay3),
176
                .z(decay_x)
177
        );
178
 
179
        mux4to1 #(8) u3 (
180
                .e(1'b1),
181
                .s(sel),
182
                .i0(sustain0),
183
                .i1(sustain1),
184
                .i2(sustain2),
185
                .i3(sustain3),
186
                .z(sustain_x)
187
        );
188
 
189
        mux4to1 #(12) u4 (
190
                .e(1'b1),
191
                .s(sel),
192
                .i0(relese0),
193
                .i1(relese1),
194
                .i2(relese2),
195
                .i3(relese3),
196
                .z(relese_x)
197
        );
198
 
199
        always @(attack_x)
200
                attack <= attack_x;
201
 
202
        always @(decay_x)
203
                decay <= decay_x;
204
 
205
        always @(sustain_x)
206
                sustain <= sustain_x;
207
 
208
        always @(relese_x)
209
                relese <= relese_x;
210
 
211
 
212
        always @(sel)
213
                envCtrx <= envCtr[sel];
214
 
215
        always @(sel)
216
                envDvnx <= envDvn[sel];
217
 
218
 
219
        // Envelope generate state machine
220
        // Determine the next envelope state
221
        always @(sel or gate or sustain)
222
        begin
223
                case (envState[sel])
224
                `ENV_IDLE:
225
                        if (gate[sel])
226
                                envStateNxt <= `ENV_ATTACK;
227
                        else
228
                                envStateNxt <= `ENV_IDLE;
229
                `ENV_ATTACK:
230
                        if (envCtrx==8'hFE) begin
231
                                if (sustain==8'hFF)
232
                                        envStateNxt <= `ENV_SUSTAIN;
233
                                else
234
                                        envStateNxt <= `ENV_DECAY;
235
                        end
236
                        else
237
                                envStateNxt <= `ENV_ATTACK;
238
                `ENV_DECAY:
239
                        if (envCtrx==sustain)
240
                                envStateNxt <= `ENV_SUSTAIN;
241
                        else
242
                                envStateNxt <= `ENV_DECAY;
243
                `ENV_SUSTAIN:
244
                        if (~gate[sel])
245
                                envStateNxt <= `ENV_RELEASE;
246
                        else
247
                                envStateNxt <= `ENV_SUSTAIN;
248
                `ENV_RELEASE: begin
249
                        if (envCtrx==8'h00)
250
                                envStateNxt <= `ENV_IDLE;
251
                        else if (gate[sel])
252
                                envStateNxt <= `ENV_SUSTAIN;
253
                        else
254
                                envStateNxt <= `ENV_RELEASE;
255
                        end
256
                // In case of hardware problem
257
                default:
258
                        envStateNxt <= `ENV_IDLE;
259
                endcase
260
        end
261
 
262
        always @(posedge clk)
263
                if (rst) begin
264
                    for (n = 0; n < pChannels; n = n + 1)
265
                        envState[n] <= `ENV_IDLE;
266
                end
267
                else if (cnt < pChannels)
268
                        envState[sel] <= envStateNxt;
269
 
270
 
271
        // Handle envelope counter
272
        always @(posedge clk)
273
                if (rst) begin
274
                    for (n = 0; n < pChannels; n = n + 1) begin
275
                        envCtr[n] <= 0;
276
                        envCtr2[n] <= 0;
277
                        icnt[n] <= 0;
278
                        iv[n] <= 0;
279
                    end
280
                end
281
                else if (cnt < pChannels) begin
282
                        case (envState[sel])
283
                        `ENV_IDLE:
284
                                begin
285
                                envCtr[sel] <= 0;
286
                                envCtr2[sel] <= 0;
287
                                icnt[sel] <= 0;
288
                                iv[sel] <= 0;
289
                                end
290
                        `ENV_SUSTAIN:
291
                                begin
292
                                envCtr2[sel] <= 0;
293
                                icnt[sel] <= 0;
294
                                iv[sel] <= sustain >> 3;
295
                                end
296
                        `ENV_ATTACK:
297
                                begin
298
                                icnt[sel] <= 0;
299
                                iv[sel] <= (8'hff - sustain) >> 3;
300
                                if (envDvnx==20'h0) begin
301
                                        envCtr2[sel] <= 0;
302
                                        envCtr[sel] <= envCtrx + 1;
303
                                end
304
                                end
305
                        `ENV_DECAY,
306
                        `ENV_RELEASE:
307
                                if (envDvnx==20'h0) begin
308
                                        envCtr[sel] <= envCtrx - 1;
309
                                        if (envCtr2[sel]==iv[sel]) begin
310
                                                envCtr2[sel] <= 0;
311
                                                if (icnt[sel] < 3'd7)
312
                                                        icnt[sel] <= icnt[sel] + 1;
313
                                        end
314
                                        else
315
                                                envCtr2[sel] <= envCtr2[sel] + 1;
316
                                end
317
                        endcase
318
                end
319
 
320
        // Determine envelope divider adjustment source
321
        always @(sel or attack or decay or relese)
322
        begin
323
                case(envState[sel])
324
                `ENV_ATTACK:    envStepPeriod <= attack;
325
                `ENV_DECAY:             envStepPeriod <= decay;
326
                `ENV_RELEASE:   envStepPeriod <= relese;
327
                default:                envStepPeriod <= 16'h0;
328
                endcase
329
        end
330
 
331
 
332
        // double the delay at appropriate points
333
        // for exponential modelling
334
        wire [19:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt[sel];
335
 
336
 
337
        // handle the clock divider
338
        // loadable down counter
339
        // This sets the period of each step of the envelope
340
        always @(posedge clk)
341
                if (rst) begin
342
                        for (n = 0; n < pChannels; n = n + 1)
343
                                envDvn[n] <= 0;
344
                end
345
                else if (cnt < pChannels) begin
346
                        if (envDvnx==20'h0)
347
                                envDvn[sel] <= envStepPeriod1;
348
                        else
349
                                envDvn[sel] <= envDvnx - 1;
350
                end
351
 
352
        assign o = envCtrx;
353
 
354
endmodule
355
 
356
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.