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

Subversion Repositories psg16

[/] [psg16/] [trunk/] [rtl/] [verilog/] [PSGEnvelopeGenerator.v] - Diff between revs 4 and 5

Only display areas with differences | Details | Blame | View Log

Rev 4 Rev 5
`timescale 1ns / 1ps
`timescale 1ns / 1ps
// ============================================================================
// ============================================================================
//        __
//        __
//   \\__/ o\    (C) 2007-2017  Robert Finch, Waterloo
//   \\__/ o\    (C) 2007-2017  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//       ||
//
//
// PSGEnvelopeGenerator.v
// PSGEnvelopeGenerator.v
//
//
// This source file is free software: you can redistribute it and/or modify 
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
// (at your option) any later version.                                      
//                                                                          
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
// GNU General Public License for more details.                             
//                                                                          
//                                                                          
// You should have received a copy of the GNU General Public License        
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//                                                                          
//                                                                          
//=============================================================================
//=============================================================================
/*
/*
        sample attack values / rates
        sample attack values / rates
        ----------------------------
        ----------------------------
        8               2ms
        8               2ms
        32              8ms
        32              8ms
        64              16ms
        64              16ms
        96              24ms
        96              24ms
        152             38ms
        152             38ms
        224             56ms
        224             56ms
        272             68ms
        272             68ms
        320             80ms
        320             80ms
        400             100ms
        400             100ms
        955             239ms
        955             239ms
        1998    500ms
        1998    500ms
        3196    800ms
        3196    800ms
        3995    1s
        3995    1s
        12784   3.2s
        12784   3.2s
        21174   5.3s
        21174   5.3s
        31960   8s
        31960   8s
 
 
        rate = 990.00ns x 256 x value
        rate = 990.00ns x 256 x value
*/
*/
 
 
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;
parameter ENV_ATTACK = 3'd1;
parameter ENV_ATTACK = 3'd1;
parameter ENV_DECAY = 3'd2;
parameter ENV_DECAY = 3'd2;
parameter ENV_SUSTAIN = 3'd3;
parameter ENV_SUSTAIN = 3'd3;
parameter ENV_RELEASE = 3'd4;
parameter ENV_RELEASE = 3'd4;
 
 
// 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;
wire release_next = envState==ENV_SUSTAIN && !gate;
wire release_next = envState==ENV_SUSTAIN && !gate;
 
 
// Envelope generate state machine
// Envelope generate state machine
// Determine the next envelope state
// Determine the next envelope state
always @*
always @*
begin
begin
envStateNxt <= envState;    // default to hold state
envStateNxt <= envState;    // default to hold state
case (envState)
case (envState)
ENV_IDLE:
ENV_IDLE:
    if (gate)
    if (gate)
        envStateNxt <= ENV_ATTACK;
        envStateNxt <= ENV_ATTACK;
ENV_ATTACK:
ENV_ATTACK:
    if (envCtr==8'hFE) begin
    if (envCtr==8'hFE) begin
        if (sustain==8'hFF)
        if (sustain==8'hFF)
            envStateNxt <= ENV_SUSTAIN;
            envStateNxt <= ENV_SUSTAIN;
        else
        else
            envStateNxt <= ENV_DECAY;
            envStateNxt <= ENV_DECAY;
    end
    end
ENV_DECAY:
ENV_DECAY:
    if (envCtr==sustain)
    if (envCtr==sustain)
        envStateNxt <= ENV_SUSTAIN;
        envStateNxt <= ENV_SUSTAIN;
ENV_SUSTAIN:
ENV_SUSTAIN:
    if (~gate)
    if (~gate)
        envStateNxt <= ENV_RELEASE;
        envStateNxt <= ENV_RELEASE;
ENV_RELEASE:
ENV_RELEASE:
    if (envCtr==8'h00)
    if (envCtr==8'h00)
        envStateNxt <= ENV_IDLE;
        envStateNxt <= ENV_IDLE;
    else if (gate)
    else if (gate)
        envStateNxt <= ENV_SUSTAIN;
        envStateNxt <= ENV_SUSTAIN;
// In case of hardware problem
// In case of hardware problem
default:
default:
    envStateNxt <= ENV_IDLE;
    envStateNxt <= ENV_IDLE;
endcase
endcase
end
end
 
 
always @(posedge clk)
always @(posedge clk)
if (rst)
if (rst)
    envState <= ENV_IDLE;
    envState <= ENV_IDLE;
else
else
    envState <= envStateNxt;
    envState <= envStateNxt;
 
 
 
 
// Handle envelope counter
// Handle envelope counter
always @(posedge clk)
always @(posedge clk)
if (rst) begin
if (rst) begin
    envCtr <= 0;
    envCtr <= 0;
    envCtr2 <= 0;
    envCtr2 <= 0;
    icnt <= 1;
    icnt <= 1;
    iv <= 0;
    iv <= 0;
end
end
else begin
else begin
case (envState)
case (envState)
ENV_IDLE:
ENV_IDLE:
    begin
    begin
    envCtr <= 0;
    envCtr <= 0;
    envCtr2 <= 0;
    envCtr2 <= 0;
    icnt <= 1;
    icnt <= 1;
    iv <= 0;
    iv <= 0;
    end
    end
ENV_SUSTAIN:
ENV_SUSTAIN:
    begin
    begin
    envCtr2 <= 0;
    envCtr2 <= 0;
    icnt <= 1;
    icnt <= 1;
    iv <= sustain >> 3;
    iv <= sustain >> 3;
    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;
        end
        end
        else
        else
            envCtr2 <= envCtr2 + 1;
            envCtr2 <= envCtr2 + 1;
    end
    end
endcase
endcase
end
end
 
 
// Determine envelope divider adjustment source
// Determine envelope divider adjustment source
always @*
always @*
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
always @(posedge clk)
always @(posedge clk)
if (rst)
if (rst)
    envDvn <= 0;
    envDvn <= 0;
else begin
else begin
    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
 
 
assign o = envCtr;
assign o = envCtr;
 
 
endmodule
endmodule
 
 
 
 

powered by: WebSVN 2.1.0

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