Line 47... |
Line 47... |
|
|
module PSGEnvelopeGenerator(rst, clk, gate, attack, decay, sustain, relese, o, envState);
|
module PSGEnvelopeGenerator(rst, clk, gate, attack, decay, sustain, relese, o, envState);
|
input rst; // reset
|
input rst; // reset
|
input clk; // core clock
|
input clk; // core clock
|
input gate;
|
input gate;
|
input [15:0] attack;
|
input [23:0] attack;
|
input [15:0] decay;
|
input [23:0] decay;
|
input [7:0] sustain; // sustain level
|
input [7:0] sustain; // sustain level
|
input [15:0] relese;
|
input [23:0] relese;
|
output [7:0] o;
|
output [7:0] o;
|
output [2:0] envState;
|
output [2:0] envState;
|
|
|
// envelope generator states
|
// envelope generator states
|
parameter ENV_IDLE = 3'd0;
|
parameter ENV_IDLE = 3'd0;
|
Line 66... |
Line 66... |
// Per channel count storage
|
// Per channel count storage
|
reg [7:0] envCtr;
|
reg [7:0] envCtr;
|
reg [7:0] envCtr2;
|
reg [7:0] envCtr2;
|
reg [7:0] iv; // interval value for decay/release
|
reg [7:0] iv; // interval value for decay/release
|
reg [2:0] icnt; // interval count
|
reg [2:0] icnt; // interval count
|
reg [19:0] envDvn;
|
reg [27:0] envDvn;
|
reg [2:0] envState;
|
reg [2:0] envState;
|
|
|
reg [2:0] envStateNxt;
|
reg [2:0] envStateNxt;
|
reg [15:0] envStepPeriod; // determines the length of one step of the envelope generator
|
reg [23:0] envStepPeriod; // determines the length of one step of the envelope generator
|
|
|
integer n;
|
integer n;
|
|
|
wire attack_next = envState==ENV_IDLE && gate;
|
wire attack_next = envState==ENV_IDLE && gate;
|
wire decay_next = envState==ENV_ATTACK && envCtr==8'hFE && sustain != 8'hFF;
|
wire decay_next = envState==ENV_ATTACK && envCtr==8'hFE && sustain != 8'hFF;
|
Line 145... |
Line 145... |
end
|
end
|
ENV_ATTACK:
|
ENV_ATTACK:
|
begin
|
begin
|
icnt <= 1;
|
icnt <= 1;
|
iv <= (8'hff - sustain) >> 3;
|
iv <= (8'hff - sustain) >> 3;
|
if (envDvn==20'h0) begin
|
if (envDvn==28'h0) begin
|
envCtr2 <= 0;
|
envCtr2 <= 0;
|
envCtr <= envCtr + 1;
|
envCtr <= envCtr + 1;
|
end
|
end
|
end
|
end
|
ENV_DECAY,
|
ENV_DECAY,
|
ENV_RELEASE:
|
ENV_RELEASE:
|
if (envDvn==20'h0) begin
|
if (envDvn==28'h0) begin
|
envCtr <= envCtr - 1;
|
envCtr <= envCtr - 1;
|
if (envCtr2==iv) begin
|
if (envCtr2==iv) begin
|
envCtr2 <= 0;
|
envCtr2 <= 0;
|
if (icnt < 3'd7)
|
if (icnt < 3'd7)
|
icnt <= icnt + 1;
|
icnt <= icnt + 1;
|
Line 172... |
Line 172... |
begin
|
begin
|
case(envState)
|
case(envState)
|
ENV_ATTACK: envStepPeriod <= attack;
|
ENV_ATTACK: envStepPeriod <= attack;
|
ENV_DECAY: envStepPeriod <= decay;
|
ENV_DECAY: envStepPeriod <= decay;
|
ENV_RELEASE: envStepPeriod <= relese;
|
ENV_RELEASE: envStepPeriod <= relese;
|
default: envStepPeriod <= 16'h0;
|
default: envStepPeriod <= 24'h0;
|
endcase
|
endcase
|
end
|
end
|
|
|
|
|
// double the delay at appropriate points
|
// double the delay at appropriate points
|
// for exponential modelling
|
// for exponential modelling
|
wire [19:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt;
|
wire [27:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt;
|
|
|
|
|
// handle the clock divider
|
// handle the clock divider
|
// loadable down counter
|
// loadable down counter
|
// This sets the period of each step of the envelope
|
// This sets the period of each step of the envelope
|
Line 194... |
Line 194... |
casex({attack_next,decay_next,release_next})
|
casex({attack_next,decay_next,release_next})
|
3'b1xx: envDvn <= {4'h0,attack};
|
3'b1xx: envDvn <= {4'h0,attack};
|
3'b01x: envDvn <= {4'h0,decay};
|
3'b01x: envDvn <= {4'h0,decay};
|
3'b001: envDvn <= {4'h0,relese};
|
3'b001: envDvn <= {4'h0,relese};
|
default:
|
default:
|
if (envDvn==20'h0)
|
if (envDvn==28'h0)
|
envDvn <= envStepPeriod1;
|
envDvn <= envStepPeriod1;
|
else
|
else
|
envDvn <= envDvn - 1;
|
envDvn <= envDvn - 1;
|
endcase
|
endcase
|
end
|
end
|