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

Subversion Repositories rtf68ksys

[/] [rtf68ksys/] [trunk/] [rtl/] [verilog/] [PSGEnvGenDec.v] - Blame information for rev 6

Go to most recent revision | 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
//`define CHANNELS8
101
 
102
// Envelope generator
103
module PSGEnvGen(rst, clk, cnt,
104
        gate,
105
        attack0, attack1, attack2, attack3,
106
        decay0, decay1, decay2, decay3,
107
        sustain0, sustain1, sustain2, sustain3,
108
        relese0, relese1, relese2, relese3,
109
`ifdef CHANNELS8
110
        attack4, attack5, attack6, attack7,
111
        decay4, decay5, decay6, decay7,
112
        sustain4, sustain5, sustain6, sustain7,
113
        relese4, relese5, relese6, relese7,
114
`endif
115
        o);
116
        parameter pChannels = 4;
117
        parameter pPrescalerBits = 5;
118
        input rst;                                                      // reset
119
        input clk;                                                      // core clock
120
        input [pPrescalerBits-1:0] cnt;          // clock rate prescaler
121
        input [3:0] attack0;
122
        input [3:0] attack1;
123
        input [3:0] attack2;
124
        input [3:0] attack3;
125
        input [3:0] decay0;
126
        input [3:0] decay1;
127
        input [3:0] decay2;
128
        input [3:0] decay3;
129
        input [3:0] sustain0;
130
        input [3:0] sustain1;
131
        input [3:0] sustain2;
132
        input [3:0] sustain3;
133
        input [3:0] relese0;
134
        input [3:0] relese1;
135
        input [3:0] relese2;
136
        input [3:0] relese3;
137
`ifdef CHANNELS8
138
        input [7:0] gate;
139
        input [3:0] attack4;
140
        input [3:0] attack5;
141
        input [3:0] attack6;
142
        input [3:0] attack7;
143
        input [3:0] decay4;
144
        input [3:0] decay5;
145
        input [3:0] decay6;
146
        input [3:0] decay7;
147
        input [3:0] sustain4;
148
        input [3:0] sustain5;
149
        input [3:0] sustain6;
150
        input [3:0] sustain7;
151
        input [3:0] relese4;
152
        input [3:0] relese5;
153
        input [3:0] relese6;
154
        input [3:0] relese7;
155
`else
156
        input [3:0] gate;
157
`endif
158
        output [7:0] o;
159
 
160
        reg [7:0] sustain;
161
        reg [15:0] attack;
162
        reg [17:0] decay;
163
        reg [17:0] relese;
164
`ifdef CHANNELS8
165
        reg [7:0] envCtr [7:0];
166
        reg [7:0] envCtr2 [7:0];  // for counting intervals
167
        reg [7:0] iv[7:0];                        // interval value for decay/release
168
        reg [2:0] icnt[7:0];                      // interval count
169
        reg [19:0] envDvn [7:0];
170
        reg [2:0] envState [7:0];
171
`else
172
        reg [7:0] envCtr [3:0];
173
        reg [7:0] envCtr2 [3:0];
174
        reg [7:0] iv[3:0];                        // interval value for decay/release
175
        reg [2:0] icnt[3:0];                      // interval count
176
        reg [19:0] envDvn [3:0];
177
        reg [2:0] envState [3:0];
178
`endif
179
        reg [2:0] envStateNxt;
180
        reg [15:0] envStepPeriod;        // determines the length of one step of the envelope generator
181
        reg [7:0] envCtrx;
182
        reg [19:0] envDvnx;
183
 
184
        wire [3:0] attack_x;
185
        wire [3:0] decay_x;
186
        wire [3:0] sustain_x;
187
        wire [3:0] relese_x;
188
 
189
        integer n;
190
 
191
        // Decodes a 4-bit code into an attack value
192
        function [15:0] AttackDecode;
193
                input [3:0] atk;
194
 
195
                begin
196
                case(atk)
197
                4'd0:   AttackDecode = 16'd8;
198
                4'd1:   AttackDecode = 16'd32;
199
                4'd2:   AttackDecode = 16'd63;
200
                4'd3:   AttackDecode = 16'd95;
201
                4'd4:   AttackDecode = 16'd150;
202
                4'd5:   AttackDecode = 16'd221;
203
                4'd6:   AttackDecode = 16'd268;
204
                4'd7:   AttackDecode = 16'd316;
205
                4'd8:   AttackDecode = 16'd395;
206
                4'd9:   AttackDecode = 16'd986;
207
                4'd10:  AttackDecode = 16'd1973;
208
                4'd11:  AttackDecode = 16'd3157;
209
                4'd12:  AttackDecode = 16'd3946;
210
                4'd13:  AttackDecode = 16'd11837;
211
                4'd14:  AttackDecode = 16'd19729;
212
                4'd15:  AttackDecode = 16'd31566;
213
                endcase
214
                end
215
 
216
        endfunction
217
 
218
        // Decodes a 4-bit code into a decay/release value
219
        function [15:0] DecayDecode;
220
                input [3:0] dec;
221
 
222
                begin
223
                case(dec)
224
                4'd0:   DecayDecode = 17'd24;
225
                4'd1:   DecayDecode = 17'd95;
226
                4'd2:   DecayDecode = 17'd190;
227
                4'd3:   DecayDecode = 17'd285;
228
                4'd4:   DecayDecode = 17'd452;
229
                4'd5:   DecayDecode = 17'd665;
230
                4'd6:   DecayDecode = 17'd808;
231
                4'd7:   DecayDecode = 17'd951;
232
                4'd8:   DecayDecode = 17'd1188;
233
                4'd9:   DecayDecode = 17'd2971;
234
                4'd10:  DecayDecode = 17'd5942;
235
                4'd11:  DecayDecode = 17'd9507;
236
                4'd12:  DecayDecode = 17'd11884;
237
                4'd13:  DecayDecode = 17'd35651;
238
                4'd14:  DecayDecode = 17'd59418;
239
                4'd15:  DecayDecode = 17'd95068;
240
                endcase
241
                end
242
 
243
        endfunction
244
 
245
`ifdef CHANNELS8
246
    wire [2:0] sel = cnt[2:0];
247
 
248
        always @(sel or
249
                attack0 or attack1 or attack2 or attack3 or
250
                attack4 or attack5 or attack6 or attack7)
251
                case (sel)
252
                0:       attack_x <= attack0;
253
                1:      attack_x <= attack1;
254
                2:      attack_x <= attack2;
255
                3:      attack_x <= attack3;
256
                4:      attack_x <= attack4;
257
                5:      attack_x <= attack5;
258
                6:      attack_x <= attack6;
259
                7:      attack_x <= attack7;
260
                endcase
261
 
262
        always @(sel or
263
                decay0 or decay1 or decay2 or decay3 or
264
                decay4 or decay5 or decay6 or decay7)
265
                case (sel)
266
                0:       decay_x <= decay0;
267
                1:      decay_x <= decay1;
268
                2:      decay_x <= decay2;
269
                3:      decay_x <= decay3;
270
                4:      decay_x <= decay4;
271
                5:      decay_x <= decay5;
272
                6:      decay_x <= decay6;
273
                7:      decay_x <= decay7;
274
                endcase
275
 
276
        always @(sel or
277
                sustain0 or sustain1 or sustain2 or sustain3 or
278
                sustain4 or sustain5 or sustain6 or sustain7)
279
                case (sel)
280
                0:       sustain <= sustain0;
281
                1:      sustain <= sustain1;
282
                2:      sustain <= sustain2;
283
                3:      sustain <= sustain3;
284
                4:      sustain <= sustain4;
285
                5:      sustain <= sustain5;
286
                6:      sustain <= sustain6;
287
                7:      sustain <= sustain7;
288
                endcase
289
 
290
        always @(sel or
291
                relese0 or relese1 or relese2 or relese3 or
292
                relese4 or relese5 or relese6 or relese7)
293
                case (sel)
294
                0:       relese <= relese0;
295
                1:      relese <= relese1;
296
                2:      relese <= relese2;
297
                3:      relese <= relese3;
298
                4:      relese <= relese4;
299
                5:      relese <= relese5;
300
                6:      relese <= relese6;
301
                7:      relese <= relese7;
302
                endcase
303
 
304
`else
305
 
306
    wire [1:0] sel = cnt[1:0];
307
 
308
        mux4to1 #(4) u1 (
309
                .e(1'b1),
310
                .s(sel),
311
                .i0(attack0),
312
                .i1(attack1),
313
                .i2(attack2),
314
                .i3(attack3),
315
                .z(attack_x)
316
        );
317
 
318
        mux4to1 #(12) u2 (
319
                .e(1'b1),
320
                .s(sel),
321
                .i0(decay0),
322
                .i1(decay1),
323
                .i2(decay2),
324
                .i3(decay3),
325
                .z(decay_x)
326
        );
327
 
328
        mux4to1 #(8) u3 (
329
                .e(1'b1),
330
                .s(sel),
331
                .i0(sustain0),
332
                .i1(sustain1),
333
                .i2(sustain2),
334
                .i3(sustain3),
335
                .z(sustain_x)
336
        );
337
 
338
        mux4to1 #(12) u4 (
339
                .e(1'b1),
340
                .s(sel),
341
                .i0(relese0),
342
                .i1(relese1),
343
                .i2(relese2),
344
                .i3(relese3),
345
                .z(relese_x)
346
        );
347
 
348
`endif
349
 
350
        always @(attack_x)
351
                attack <= AttackDecode(attack_x);
352
 
353
        always @(decay_x)
354
                decay <= DecayDecode(decay_x);
355
 
356
        always @(sustain_x)
357
                sustain <= {sustain_x,sustain_x};
358
 
359
        always @(relese_x)
360
                relese <= DecayDecode(relese_x);
361
 
362
 
363
        always @(sel)
364
                envCtrx <= envCtr[sel];
365
 
366
        always @(sel)
367
                envDvnx <= envDvn[sel];
368
 
369
 
370
        // Envelope generate state machine
371
        // Determine the next envelope state
372
        always @(sel or gate or sustain)
373
        begin
374
                case (envState[sel])
375
                `ENV_IDLE:
376
                        if (gate[sel])
377
                                envStateNxt <= `ENV_ATTACK;
378
                        else
379
                                envStateNxt <= `ENV_IDLE;
380
                `ENV_ATTACK:
381
                        if (envCtrx==8'hFE) begin
382
                                if (sustain==8'hFF)
383
                                        envStateNxt <= `ENV_SUSTAIN;
384
                                else
385
                                        envStateNxt <= `ENV_DECAY;
386
                        end
387
                        else
388
                                envStateNxt <= `ENV_ATTACK;
389
                `ENV_DECAY:
390
                        if (envCtrx==sustain)
391
                                envStateNxt <= `ENV_SUSTAIN;
392
                        else
393
                                envStateNxt <= `ENV_DECAY;
394
                `ENV_SUSTAIN:
395
                        if (~gate[sel])
396
                                envStateNxt <= `ENV_RELEASE;
397
                        else
398
                                envStateNxt <= `ENV_SUSTAIN;
399
                `ENV_RELEASE: begin
400
                        if (envCtrx==8'h00)
401
                                envStateNxt <= `ENV_IDLE;
402
                        else if (gate[sel])
403
                                envStateNxt <= `ENV_SUSTAIN;
404
                        else
405
                                envStateNxt <= `ENV_RELEASE;
406
                        end
407
                // In case of hardware problem
408
                default:
409
                        envStateNxt <= `ENV_IDLE;
410
                endcase
411
        end
412
 
413
        always @(posedge clk)
414
                if (rst) begin
415
                    for (n = 0; n < pChannels; n = n + 1)
416
                        envState[n] <= `ENV_IDLE;
417
                end
418
                else if (cnt < pChannels)
419
                        envState[sel] <= envStateNxt;
420
 
421
 
422
        // Handle envelope counter
423
        always @(posedge clk)
424
                if (rst) begin
425
                    for (n = 0; n < pChannels; n = n + 1) begin
426
                        envCtr[n] <= 0;
427
                        envCtr2[n] <= 0;
428
                        icnt[n] <= 0;
429
                        iv[n] <= 0;
430
                    end
431
                end
432
                else if (cnt < pChannels) begin
433
                        case (envState[sel])
434
                        `ENV_IDLE:
435
                                begin
436
                                envCtr[sel] <= 0;
437
                                envCtr2[sel] <= 0;
438
                                icnt[sel] <= 0;
439
                                iv[sel] <= 0;
440
                                end
441
                        `ENV_SUSTAIN:
442
                                begin
443
                                envCtr2[sel] <= 0;
444
                                icnt[sel] <= 0;
445
                                iv[sel] <= sustain >> 3;
446
                                end
447
                        `ENV_ATTACK:
448
                                begin
449
                                icnt[sel] <= 0;
450
                                iv[sel] <= (8'hff - sustain) >> 3;
451
                                if (envDvnx==20'h0) begin
452
                                        envCtr2[sel] <= 0;
453
                                        envCtr[sel] <= envCtrx + 1;
454
                                end
455
                                end
456
                        `ENV_DECAY,
457
                        `ENV_RELEASE:
458
                                if (envDvnx==20'h0) begin
459
                                        envCtr[sel] <= envCtrx - 1;
460
                                        if (envCtr2[sel]==iv[sel]) begin
461
                                                envCtr2[sel] <= 0;
462
                                                if (icnt[sel] < 3'd7)
463
                                                        icnt[sel] <= icnt[sel] + 1;
464
                                        end
465
                                        else
466
                                                envCtr2[sel] <= envCtr2[sel] + 1;
467
                                end
468
                        endcase
469
                end
470
 
471
        // Determine envelope divider adjustment source
472
        always @(sel or attack or decay or relese)
473
        begin
474
                case(envState[sel])
475
                `ENV_ATTACK:    envStepPeriod <= attack;
476
                `ENV_DECAY:             envStepPeriod <= decay;
477
                `ENV_RELEASE:   envStepPeriod <= relese;
478
                default:                envStepPeriod <= 16'h0;
479
                endcase
480
        end
481
 
482
 
483
        // double the delay at appropriate points
484
        // for exponential modelling
485
        wire [19:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt[sel];
486
 
487
 
488
        // handle the clock divider
489
        // loadable down counter
490
        // This sets the period of each step of the envelope
491
        always @(posedge clk)
492
                if (rst) begin
493
                        for (n = 0; n < pChannels; n = n + 1)
494
                                envDvn[n] <= 0;
495
                end
496
                else if (cnt < pChannels) begin
497
                        if (envDvnx==20'h0)
498
                                envDvn[sel] <= envStepPeriod1;
499
                        else
500
                                envDvn[sel] <= envDvnx - 1;
501
                end
502
 
503
        assign o = envCtrx;
504
 
505
endmodule
506
 
507
 

powered by: WebSVN 2.1.0

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