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

Subversion Repositories psg16

[/] [psg16/] [trunk/] [rtl/] [verilog/] [PSGEnvelopeGenerator.v] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4
//   \\__/ o\    (C) 2007-2017  Robert Finch, Waterloo
5
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch<remove>@finitron.ca
7
//       ||
8
//
9
// PSGEnvelopeGenerator.v
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//                                                                          
24
//=============================================================================
25
/*
26
        sample attack values / rates
27
        ----------------------------
28
        8               2ms
29
        32              8ms
30
        64              16ms
31
        96              24ms
32
        152             38ms
33
        224             56ms
34
        272             68ms
35
        320             80ms
36
        400             100ms
37
        955             239ms
38
        1998    500ms
39
        3196    800ms
40
        3995    1s
41
        12784   3.2s
42
        21174   5.3s
43
        31960   8s
44
 
45
        rate = 990.00ns x 256 x value
46
*/
47
 
48
module PSGEnvelopeGenerator(rst, clk, gate, attack, decay, sustain, relese, o, envState);
49
input rst;                                      // reset
50
input clk;                                      // core clock
51
input gate;
52 5 robfinch
input [23:0] attack;
53
input [23:0] decay;
54 4 robfinch
input [7:0] sustain;        // sustain level
55 5 robfinch
input [23:0] relese;
56 4 robfinch
output [7:0] o;
57
output [2:0] envState;
58
 
59
// envelope generator states
60
parameter ENV_IDLE = 3'd0;
61
parameter ENV_ATTACK = 3'd1;
62
parameter ENV_DECAY = 3'd2;
63
parameter ENV_SUSTAIN = 3'd3;
64
parameter ENV_RELEASE = 3'd4;
65
 
66
// Per channel count storage
67
reg [7:0] envCtr;
68
reg [7:0] envCtr2;
69
reg [7:0] iv;                        // interval value for decay/release
70
reg [2:0] icnt;                 // interval count
71 5 robfinch
reg [27:0] envDvn;
72 4 robfinch
reg [2:0] envState;
73
 
74
reg [2:0] envStateNxt;
75 5 robfinch
reg [23:0] envStepPeriod;        // determines the length of one step of the envelope generator
76 4 robfinch
 
77
integer n;
78
 
79
wire attack_next = envState==ENV_IDLE && gate;
80
wire decay_next = envState==ENV_ATTACK && envCtr==8'hFE && sustain != 8'hFF;
81
wire release_next = envState==ENV_SUSTAIN && !gate;
82
 
83
// Envelope generate state machine
84
// Determine the next envelope state
85
always @*
86
begin
87
envStateNxt <= envState;    // default to hold state
88
case (envState)
89
ENV_IDLE:
90
    if (gate)
91
        envStateNxt <= ENV_ATTACK;
92
ENV_ATTACK:
93
    if (envCtr==8'hFE) begin
94
        if (sustain==8'hFF)
95
            envStateNxt <= ENV_SUSTAIN;
96
        else
97
            envStateNxt <= ENV_DECAY;
98
    end
99
ENV_DECAY:
100
    if (envCtr==sustain)
101
        envStateNxt <= ENV_SUSTAIN;
102
ENV_SUSTAIN:
103
    if (~gate)
104
        envStateNxt <= ENV_RELEASE;
105
ENV_RELEASE:
106
    if (envCtr==8'h00)
107
        envStateNxt <= ENV_IDLE;
108
    else if (gate)
109
        envStateNxt <= ENV_SUSTAIN;
110
// In case of hardware problem
111
default:
112
    envStateNxt <= ENV_IDLE;
113
endcase
114
end
115
 
116
always @(posedge clk)
117
if (rst)
118
    envState <= ENV_IDLE;
119
else
120
    envState <= envStateNxt;
121
 
122
 
123
// Handle envelope counter
124
always @(posedge clk)
125
if (rst) begin
126
    envCtr <= 0;
127
    envCtr2 <= 0;
128
    icnt <= 1;
129
    iv <= 0;
130
end
131
else begin
132
case (envState)
133
ENV_IDLE:
134
    begin
135
    envCtr <= 0;
136
    envCtr2 <= 0;
137
    icnt <= 1;
138
    iv <= 0;
139
    end
140
ENV_SUSTAIN:
141
    begin
142
    envCtr2 <= 0;
143
    icnt <= 1;
144
    iv <= sustain >> 3;
145
    end
146
ENV_ATTACK:
147
    begin
148
    icnt <= 1;
149
    iv <= (8'hff - sustain) >> 3;
150 5 robfinch
    if (envDvn==28'h0) begin
151 4 robfinch
        envCtr2 <= 0;
152
        envCtr <= envCtr + 1;
153
    end
154
    end
155
ENV_DECAY,
156
ENV_RELEASE:
157 5 robfinch
    if (envDvn==28'h0) begin
158 4 robfinch
        envCtr <= envCtr - 1;
159
        if (envCtr2==iv) begin
160
            envCtr2 <= 0;
161
            if (icnt < 3'd7)
162
                icnt <= icnt + 1;
163
        end
164
        else
165
            envCtr2 <= envCtr2 + 1;
166
    end
167
endcase
168
end
169
 
170
// Determine envelope divider adjustment source
171
always @*
172
begin
173
case(envState)
174
ENV_ATTACK:         envStepPeriod <= attack;
175
ENV_DECAY:              envStepPeriod <= decay;
176
ENV_RELEASE:    envStepPeriod <= relese;
177 5 robfinch
default:                envStepPeriod <= 24'h0;
178 4 robfinch
endcase
179
end
180
 
181
 
182
// double the delay at appropriate points
183
// for exponential modelling
184 5 robfinch
wire [27:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt;
185 4 robfinch
 
186
 
187
// handle the clock divider
188
// loadable down counter
189
// This sets the period of each step of the envelope
190
always @(posedge clk)
191
if (rst)
192
    envDvn <= 0;
193
else begin
194
    casex({attack_next,decay_next,release_next})
195
    3'b1xx: envDvn <= {4'h0,attack};
196
    3'b01x: envDvn <= {4'h0,decay};
197
    3'b001: envDvn <= {4'h0,relese};
198
    default:
199 5 robfinch
        if (envDvn==28'h0)
200 4 robfinch
            envDvn <= envStepPeriod1;
201
        else
202
            envDvn <= envDvn - 1;
203
    endcase
204
end
205
 
206
assign o = envCtr;
207
 
208
endmodule
209
 

powered by: WebSVN 2.1.0

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