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

Subversion Repositories psg16

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//  (C) 2007,2012  Robert Finch
4
//  robfinch<remove>@opencores.org
5
//      All rights reserved.
6
//
7
//      PSGEnvGen.v
8
//      Version 1.1
9
//
10
//      ADSR envelope generator.
11
//
12
// This source file is free software: you can redistribute it and/or modify 
13
// it under the terms of the GNU Lesser General Public License as published 
14
// by the Free Software Foundation, either version 3 of the License, or     
15
// (at your option) any later version.                                      
16
//                                                                          
17
// This source file is distributed in the hope that it will be useful,      
18
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
19
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
20
// GNU General Public License for more details.                             
21
//                                                                          
22
// You should have received a copy of the GNU General Public License        
23
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
24
//
25
//
26
//    This component isn't really meant to be used in isolation. It is
27
//    intended to be integrated into a larger audio component (eg SID
28
//    emulator). The host component should take care of wrapping the control
29
//    signals into a register array.
30
//
31
//    The 'cnt' signal acts a prescaler used to determine the base frequency
32
//    used to generate envelopes. The core expects to be driven at
33
//    approximately a 1.0MHz rate for proper envelope generation. This is
34
//    accomplished using the 'cnt' signal, which should the output of a
35
//    counter used to divide the master clock frequency down to approximately
36
//    a 1MHz rate. Therefore, the master clock frequency must be at least 4MHz
37
//    for a 4 channel generator, 8MHZ for an 8 channel generator. The test
38
//    system uses a 66.667MHz master clock and 'cnt' is the output of a seven
39
//    bit counter that divides by 66.
40
//
41
//    Note the resource space optimization. Rather than simply build a single
42
//    channel ADSR envelope generator and instantiate it four or eight times,
43
//    This unit uses a single envelope generator and time-multiplexes the
44
//    controls from four (or eight) different channels. The ADSR is just
45
//      complex enough that it's less expensive resource wise to multiplex the
46
//      control signals. The luxury of time division multiplexing can be used
47
//      here since audio signals are low frequency. The time division multiplex
48
//      means that we need a clock that's four (or eight) times faster than
49
//      would be needed if independent ADSR's were used. This probably isn't a
50
//      problem for most cases.
51
//
52
//      Spartan3
53
//      Webpack 9.1i xc3s1000-4ft256
54
//      522 LUTs / 271 slices / 81.155 MHz (speed)
55
//============================================================================ */
56
 
57
/*
58
        code sample attack values / rates
59
        ---------------------------------
60
 
61
        1       32              8ms
62
        2       64              16ms
63
        3       96              24ms
64
        4       152             38ms
65
        5       224             56ms
66
        6       272             68ms
67
        7       320             80ms
68
        8       400             100ms
69
        9       955             239ms
70
        10      1998    500ms
71
        11      3196    800ms
72
        12      3995    1s
73
        13      12784   3.2s
74
        14      21174   5.3s
75
        15      31960   8s
76
 
77
        rate = 990.00ns x 256 x value
78
*/
79
 
80
 
81
// envelope generator states
82
`define ENV_IDLE        0
83
`define ENV_ATTACK      1
84
`define ENV_DECAY       2
85
`define ENV_SUSTAIN     3
86
`define ENV_RELEASE     4
87
 
88
//`define CHANNELS8
89
 
90
// Envelope generator
91
module PSGEnvGen(rst, clk, cnt,
92
        gate,
93
        attack0, attack1, attack2, attack3,
94
        decay0, decay1, decay2, decay3,
95
        sustain0, sustain1, sustain2, sustain3,
96
        relese0, relese1, relese2, relese3,
97
`ifdef CHANNELS8
98
        attack4, attack5, attack6, attack7,
99
        decay4, decay5, decay6, decay7,
100
        sustain4, sustain5, sustain6, sustain7,
101
        relese4, relese5, relese6, relese7,
102
`endif
103
        o);
104
        parameter pChannels = 4;
105
        parameter pPrescalerBits = 5;
106
        input rst;                                                      // reset
107
        input clk;                                                      // core clock
108
        input [pPrescalerBits-1:0] cnt;          // clock rate prescaler
109
        input [3:0] attack0;
110
        input [3:0] attack1;
111
        input [3:0] attack2;
112
        input [3:0] attack3;
113
        input [3:0] decay0;
114
        input [3:0] decay1;
115
        input [3:0] decay2;
116
        input [3:0] decay3;
117
        input [3:0] sustain0;
118
        input [3:0] sustain1;
119
        input [3:0] sustain2;
120
        input [3:0] sustain3;
121
        input [3:0] relese0;
122
        input [3:0] relese1;
123
        input [3:0] relese2;
124
        input [3:0] relese3;
125
`ifdef CHANNELS8
126
        input [7:0] gate;
127
        input [3:0] attack4;
128
        input [3:0] attack5;
129
        input [3:0] attack6;
130
        input [3:0] attack7;
131
        input [3:0] decay4;
132
        input [3:0] decay5;
133
        input [3:0] decay6;
134
        input [3:0] decay7;
135
        input [3:0] sustain4;
136
        input [3:0] sustain5;
137
        input [3:0] sustain6;
138
        input [3:0] sustain7;
139
        input [3:0] relese4;
140
        input [3:0] relese5;
141
        input [3:0] relese6;
142
        input [3:0] relese7;
143
`else
144
        input [3:0] gate;
145
`endif
146
        output [7:0] o;
147
 
148
        reg [7:0] sustain;
149
        reg [15:0] attack;
150
        reg [17:0] decay;
151
        reg [17:0] relese;
152
`ifdef CHANNELS8
153
        reg [7:0] envCtr [7:0];
154
        reg [7:0] envCtr2 [7:0];  // for counting intervals
155
        reg [7:0] iv[7:0];                        // interval value for decay/release
156
        reg [2:0] icnt[7:0];                      // interval count
157
        reg [19:0] envDvn [7:0];
158
        reg [2:0] envState [7:0];
159
`else
160
        reg [7:0] envCtr [3:0];
161
        reg [7:0] envCtr2 [3:0];
162
        reg [7:0] iv[3:0];                        // interval value for decay/release
163
        reg [2:0] icnt[3:0];                      // interval count
164
        reg [19:0] envDvn [3:0];
165
        reg [2:0] envState [3:0];
166
`endif
167
        reg [2:0] envStateNxt;
168
        reg [15:0] envStepPeriod;        // determines the length of one step of the envelope generator
169
        reg [7:0] envCtrx;
170
        reg [19:0] envDvnx;
171
 
172
        wire [3:0] attack_x;
173
        wire [3:0] decay_x;
174
        wire [3:0] sustain_x;
175
        wire [3:0] relese_x;
176
 
177
        integer n;
178
 
179
        // Decodes a 4-bit code into an attack value
180
        function [15:0] AttackDecode;
181
                input [3:0] atk;
182
 
183
                begin
184
                case(atk)
185
                4'd0:   AttackDecode = 16'd8;
186
                4'd1:   AttackDecode = 16'd32;
187
                4'd2:   AttackDecode = 16'd63;
188
                4'd3:   AttackDecode = 16'd95;
189
                4'd4:   AttackDecode = 16'd150;
190
                4'd5:   AttackDecode = 16'd221;
191
                4'd6:   AttackDecode = 16'd268;
192
                4'd7:   AttackDecode = 16'd316;
193
                4'd8:   AttackDecode = 16'd395;
194
                4'd9:   AttackDecode = 16'd986;
195
                4'd10:  AttackDecode = 16'd1973;
196
                4'd11:  AttackDecode = 16'd3157;
197
                4'd12:  AttackDecode = 16'd3946;
198
                4'd13:  AttackDecode = 16'd11837;
199
                4'd14:  AttackDecode = 16'd19729;
200
                4'd15:  AttackDecode = 16'd31566;
201
                endcase
202
                end
203
 
204
        endfunction
205
 
206
        // Decodes a 4-bit code into a decay/release value
207
        function [15:0] DecayDecode;
208
                input [3:0] dec;
209
 
210
                begin
211
                case(dec)
212
                4'd0:   DecayDecode = 17'd24;
213
                4'd1:   DecayDecode = 17'd95;
214
                4'd2:   DecayDecode = 17'd190;
215
                4'd3:   DecayDecode = 17'd285;
216
                4'd4:   DecayDecode = 17'd452;
217
                4'd5:   DecayDecode = 17'd665;
218
                4'd6:   DecayDecode = 17'd808;
219
                4'd7:   DecayDecode = 17'd951;
220
                4'd8:   DecayDecode = 17'd1188;
221
                4'd9:   DecayDecode = 17'd2971;
222
                4'd10:  DecayDecode = 17'd5942;
223
                4'd11:  DecayDecode = 17'd9507;
224
                4'd12:  DecayDecode = 17'd11884;
225
                4'd13:  DecayDecode = 17'd35651;
226
                4'd14:  DecayDecode = 17'd59418;
227
                4'd15:  DecayDecode = 17'd95068;
228
                endcase
229
                end
230
 
231
        endfunction
232
 
233
`ifdef CHANNELS8
234
    wire [2:0] sel = cnt[2:0];
235
 
236
        always @(sel or
237
                attack0 or attack1 or attack2 or attack3 or
238
                attack4 or attack5 or attack6 or attack7)
239
                case (sel)
240
                0:       attack_x <= attack0;
241
                1:      attack_x <= attack1;
242
                2:      attack_x <= attack2;
243
                3:      attack_x <= attack3;
244
                4:      attack_x <= attack4;
245
                5:      attack_x <= attack5;
246
                6:      attack_x <= attack6;
247
                7:      attack_x <= attack7;
248
                endcase
249
 
250
        always @(sel or
251
                decay0 or decay1 or decay2 or decay3 or
252
                decay4 or decay5 or decay6 or decay7)
253
                case (sel)
254
                0:       decay_x <= decay0;
255
                1:      decay_x <= decay1;
256
                2:      decay_x <= decay2;
257
                3:      decay_x <= decay3;
258
                4:      decay_x <= decay4;
259
                5:      decay_x <= decay5;
260
                6:      decay_x <= decay6;
261
                7:      decay_x <= decay7;
262
                endcase
263
 
264
        always @(sel or
265
                sustain0 or sustain1 or sustain2 or sustain3 or
266
                sustain4 or sustain5 or sustain6 or sustain7)
267
                case (sel)
268
                0:       sustain <= sustain0;
269
                1:      sustain <= sustain1;
270
                2:      sustain <= sustain2;
271
                3:      sustain <= sustain3;
272
                4:      sustain <= sustain4;
273
                5:      sustain <= sustain5;
274
                6:      sustain <= sustain6;
275
                7:      sustain <= sustain7;
276
                endcase
277
 
278
        always @(sel or
279
                relese0 or relese1 or relese2 or relese3 or
280
                relese4 or relese5 or relese6 or relese7)
281
                case (sel)
282
                0:       relese <= relese0;
283
                1:      relese <= relese1;
284
                2:      relese <= relese2;
285
                3:      relese <= relese3;
286
                4:      relese <= relese4;
287
                5:      relese <= relese5;
288
                6:      relese <= relese6;
289
                7:      relese <= relese7;
290
                endcase
291
 
292
`else
293
 
294
    wire [1:0] sel = cnt[1:0];
295
 
296
        mux4to1 #(4) u1 (
297
                .e(1'b1),
298
                .s(sel),
299
                .i0(attack0),
300
                .i1(attack1),
301
                .i2(attack2),
302
                .i3(attack3),
303
                .z(attack_x)
304
        );
305
 
306
        mux4to1 #(12) u2 (
307
                .e(1'b1),
308
                .s(sel),
309
                .i0(decay0),
310
                .i1(decay1),
311
                .i2(decay2),
312
                .i3(decay3),
313
                .z(decay_x)
314
        );
315
 
316
        mux4to1 #(8) u3 (
317
                .e(1'b1),
318
                .s(sel),
319
                .i0(sustain0),
320
                .i1(sustain1),
321
                .i2(sustain2),
322
                .i3(sustain3),
323
                .z(sustain_x)
324
        );
325
 
326
        mux4to1 #(12) u4 (
327
                .e(1'b1),
328
                .s(sel),
329
                .i0(relese0),
330
                .i1(relese1),
331
                .i2(relese2),
332
                .i3(relese3),
333
                .z(relese_x)
334
        );
335
 
336
`endif
337
 
338
        always @(attack_x)
339
                attack <= AttackDecode(attack_x);
340
 
341
        always @(decay_x)
342
                decay <= DecayDecode(decay_x);
343
 
344
        always @(sustain_x)
345
                sustain <= {sustain_x,sustain_x};
346
 
347
        always @(relese_x)
348
                relese <= DecayDecode(relese_x);
349
 
350
 
351
        always @(sel)
352
                envCtrx <= envCtr[sel];
353
 
354
        always @(sel)
355
                envDvnx <= envDvn[sel];
356
 
357
 
358
        // Envelope generate state machine
359
        // Determine the next envelope state
360
        always @(sel or gate or sustain)
361
        begin
362
                case (envState[sel])
363
                `ENV_IDLE:
364
                        if (gate[sel])
365
                                envStateNxt <= `ENV_ATTACK;
366
                        else
367
                                envStateNxt <= `ENV_IDLE;
368
                `ENV_ATTACK:
369
                        if (envCtrx==8'hFE) begin
370
                                if (sustain==8'hFF)
371
                                        envStateNxt <= `ENV_SUSTAIN;
372
                                else
373
                                        envStateNxt <= `ENV_DECAY;
374
                        end
375
                        else
376
                                envStateNxt <= `ENV_ATTACK;
377
                `ENV_DECAY:
378
                        if (envCtrx==sustain)
379
                                envStateNxt <= `ENV_SUSTAIN;
380
                        else
381
                                envStateNxt <= `ENV_DECAY;
382
                `ENV_SUSTAIN:
383
                        if (~gate[sel])
384
                                envStateNxt <= `ENV_RELEASE;
385
                        else
386
                                envStateNxt <= `ENV_SUSTAIN;
387
                `ENV_RELEASE: begin
388
                        if (envCtrx==8'h00)
389
                                envStateNxt <= `ENV_IDLE;
390
                        else if (gate[sel])
391
                                envStateNxt <= `ENV_SUSTAIN;
392
                        else
393
                                envStateNxt <= `ENV_RELEASE;
394
                        end
395
                // In case of hardware problem
396
                default:
397
                        envStateNxt <= `ENV_IDLE;
398
                endcase
399
        end
400
 
401
        always @(posedge clk)
402
                if (rst) begin
403
                    for (n = 0; n < pChannels; n = n + 1)
404
                        envState[n] <= `ENV_IDLE;
405
                end
406
                else if (cnt < pChannels)
407
                        envState[sel] <= envStateNxt;
408
 
409
 
410
        // Handle envelope counter
411
        always @(posedge clk)
412
                if (rst) begin
413
                    for (n = 0; n < pChannels; n = n + 1) begin
414
                        envCtr[n] <= 0;
415
                        envCtr2[n] <= 0;
416
                        icnt[n] <= 0;
417
                        iv[n] <= 0;
418
                    end
419
                end
420
                else if (cnt < pChannels) begin
421
                        case (envState[sel])
422
                        `ENV_IDLE:
423
                                begin
424
                                envCtr[sel] <= 0;
425
                                envCtr2[sel] <= 0;
426
                                icnt[sel] <= 0;
427
                                iv[sel] <= 0;
428
                                end
429
                        `ENV_SUSTAIN:
430
                                begin
431
                                envCtr2[sel] <= 0;
432
                                icnt[sel] <= 0;
433
                                iv[sel] <= sustain >> 3;
434
                                end
435
                        `ENV_ATTACK:
436
                                begin
437
                                icnt[sel] <= 0;
438
                                iv[sel] <= (8'hff - sustain) >> 3;
439
                                if (envDvnx==20'h0) begin
440
                                        envCtr2[sel] <= 0;
441
                                        envCtr[sel] <= envCtrx + 1;
442
                                end
443
                                end
444
                        `ENV_DECAY,
445
                        `ENV_RELEASE:
446
                                if (envDvnx==20'h0) begin
447
                                        envCtr[sel] <= envCtrx - 1;
448
                                        if (envCtr2[sel]==iv[sel]) begin
449
                                                envCtr2[sel] <= 0;
450
                                                if (icnt[sel] < 3'd7)
451
                                                        icnt[sel] <= icnt[sel] + 1;
452
                                        end
453
                                        else
454
                                                envCtr2[sel] <= envCtr2[sel] + 1;
455
                                end
456
                        endcase
457
                end
458
 
459
        // Determine envelope divider adjustment source
460
        always @(sel or attack or decay or relese)
461
        begin
462
                case(envState[sel])
463
                `ENV_ATTACK:    envStepPeriod <= attack;
464
                `ENV_DECAY:             envStepPeriod <= decay;
465
                `ENV_RELEASE:   envStepPeriod <= relese;
466
                default:                envStepPeriod <= 16'h0;
467
                endcase
468
        end
469
 
470
 
471
        // double the delay at appropriate points
472
        // for exponential modelling
473
        wire [19:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt[sel];
474
 
475
 
476
        // handle the clock divider
477
        // loadable down counter
478
        // This sets the period of each step of the envelope
479
        always @(posedge clk)
480
                if (rst) begin
481
                        for (n = 0; n < pChannels; n = n + 1)
482
                                envDvn[n] <= 0;
483
                end
484
                else if (cnt < pChannels) begin
485
                        if (envDvnx==20'h0)
486
                                envDvn[sel] <= envStepPeriod1;
487
                        else
488
                                envDvn[sel] <= envDvnx - 1;
489
                end
490
 
491
        assign o = envCtrx;
492
 
493
endmodule
494
 
495
 

powered by: WebSVN 2.1.0

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