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

Subversion Repositories jt51

[/] [jt51/] [trunk/] [jt51/] [jt51_envelope.v] - Rev 2

Compare with Previous | Blame | View Log

/*  This file is part of JT51.
 
    JT51 is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    JT51 is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with JT51.  If not, see <http://www.gnu.org/licenses/>.
 
	Author: Jose Tejada Gomez. Twitter: @topapate
	Version: 1.0
	Date: 27-10-2016
	*/
 
`timescale 1ns / 1ps
 
/*
 
	tab size 4
 
*/
 
module jt51_envelope(
	`ifdef TEST_SUPPORT
	input				test_eg,
	`endif
	input			 	rst,
	input			 	clk,
	input				zero,
	// envelope configuration
	input		[4:0]	keycode_III,
	input		[4:0]	arate,
	input		[4:0]	rate1,	
	input		[4:0]	rate2,	
	input		[3:0]	rrate,	
	input		[3:0]	d1l,
	input		[1:0]	ks,	
	// envelope operation
	input				keyon,
	input				keyoff,
	// envelope number
	input		[6:0]	tl,
	input		[6:0]	am,
	input		[1:0]	ams,
	input				amsen,
	output	reg	[9:0]	eg
);
 
 // eg[9:6] -> direct attenuation (divide by 2)
		// eg[5:0] -> mantisa attenuation (uses LUT)
		// 1 LSB of eg is -0.09257 dB
 
parameter ATTACK=2'd0, DECAY1=2'd1, DECAY2=2'd2, RELEASE=2'd3;
 
reg		[4:0]	d1level;
reg		[2:0]	cnt_V;
reg		[5:0]	rate_IV;
wire	[6:0]	tl_out;
wire	[1:0]	ams_out;
wire			amsen_out;
reg		[9:0]	eg_in, eg_out_III, eg_out_IV, eg_out_V, eg_out_VI;
wire	[9:0]	eg_out;
reg		[11:0]	sum_eg_tl;
 
reg 	step_V, step_VI;
reg		sum_up;
reg		keyon_II, keyon_III, keyon_IV, keyon_V, keyon_VI;
reg		keyoff_II;
reg 	[5:0]	rate_V;
reg		[5:1]	rate_VI;
 
reg		[4:0]	rate1_II, rate2_II, arate_II;
reg		[3:0]	rrate_II;
 
// remember: { log_msb, pow_addr } <= log_val[11:0] + { tl, 5'd0 } + { eg, 2'd0 };
 
reg		[1:0]	eg_cnt_base;
reg		[14:0]	eg_cnt;
 
reg		[8:0]	am_final;
 
always @(*) begin : sum_eg_and_tl
	casex( {amsen_out, ams_out } )
		3'b0xx,3'b100: am_final <= 9'd0;
		3'b101: am_final <= { 2'b00, am };
		3'b110: am_final <= { 1'b0, am, 1'b0};
		3'b111: am_final <= { am, 2'b0      };
	endcase
	`ifdef TEST_SUPPORT
	if( test_eg && tl_out!=7'd0 )
		sum_eg_tl <= 11'd0;
	else
	`endif
		sum_eg_tl <= { tl_out,   3'd0 } 
		           + eg_in 
				   + { am_final, 1'b0 };
end
 
always @(posedge clk) begin : envelope_counter
	if( rst ) begin
		eg_cnt_base	<= 2'd0;
		eg_cnt		<=15'd0;
	end
	else begin
		if( zero ) begin
			// envelope counter increases every 3 output samples,
			// there is one sample every 32 clock ticks
			if( eg_cnt_base == 2'd2 ) begin
				eg_cnt 		<= eg_cnt + 1'b1;
				eg_cnt_base	<= 2'd0;
			end
			else eg_cnt_base <= eg_cnt_base + 1'b1;
		end
	end
end
 
wire			cnt_out; // = all_cnt_last[3*31-1:3*30];
 
reg		[6:0]	pre_rate_III;
reg		[4:0]	cfg_III;
wire	[1:0]	ks_III;
 
always @(*) begin : pre_rate_calc
	if( cfg_III == 5'd0 )
		pre_rate_III <= 6'd0;
	else
		case( ks_III )
			2'd3:	pre_rate_III <= { cfg_III, 1'b0 } + keycode_III;
			2'd2:	pre_rate_III <= { cfg_III, 1'b0 } + { 1'b0, keycode_III[4:1] };
			2'd1:	pre_rate_III <= { cfg_III, 1'b0 } + { 2'b0, keycode_III[4:2] };
			2'd0:	pre_rate_III <= { cfg_III, 1'b0 } + { 3'b0, keycode_III[4:3] };
		endcase
end
 
 
 
reg [7:0]	step_idx;
reg	[1:0]	state_in_III, state_in_IV, state_in_V, state_in_VI;
wire [1:0]	state_out;
 
always @(*) begin : rate_step
	if( rate_V[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x
		if( rate_V[5:2]==4'hf && state_in_V == ATTACK)
			step_idx <= 8'b11111111; // Maximum attack speed, rates 60&61
		else
		case( rate_V[1:0] )
			2'd0: step_idx <= 8'b00000000;
			2'd1: step_idx <= 8'b10001000; // 2
			2'd2: step_idx <= 8'b10101010; // 4
			2'd3: step_idx <= 8'b11101110; // 6
		endcase
	end
	else begin
		if( rate_V[5:2]==4'd0 && state_in_V != ATTACK)
			step_idx <= 8'b11111110; // limit slowest decay rate_IV
		else
		case( rate_V[1:0] )
			2'd0: step_idx <= 8'b10101010; // 4
			2'd1: step_idx <= 8'b11101010; // 5
			2'd2: step_idx <= 8'b11101110; // 6
			2'd3: step_idx <= 8'b11111110; // 7
		endcase	
	end 
	// a rate_IV of zero keeps the level still
	step_V <= rate_V[5:1]==5'd0 ? 1'b0 : step_idx[ cnt_V ];
end
 
 
 
wire	ar_off_VI;
reg		ar_off_III;
 
reg [8:0] ar_sum0;
reg [9:0] ar_result, ar_sum;
 
always @(*) begin : ar_calculation
	casex( rate_VI[5:2] )
		default: ar_sum0 <= eg_out_VI[9:4] + 1'd1;
		4'b1100: ar_sum0 <= eg_out_VI[9:4] + 1'd1;		
		4'b1101: ar_sum0 <= eg_out_VI[9:3] + 1'd1;
		4'b111x: ar_sum0 <= eg_out_VI[9:2] + 1'd1;
	endcase
	if( rate_VI[5:4] == 2'b11 )
		ar_sum <= step_VI ? { ar_sum0, 1'b0 } : { 1'b0, ar_sum0 };
	else
		ar_sum <= step_VI ? { 1'b0, ar_sum0 } : 10'd0;
	ar_result <= ar_sum<eg_out_VI ? eg_out_VI-ar_sum : 10'd0;
end
 
always @(posedge clk) begin
	// I
	if( d1l == 4'd15 )
		d1level <= 5'h10; // 48dB 
	else
		d1level <= d1l;
	keyon_II <= keyon;
	keyoff_II<= keyoff;
	{ arate_II, rate1_II, rate2_II, rrate_II } <= { arate, rate1, rate2, rrate };
 
	//	II
	ar_off_III	<= arate_II == 5'h1f;
	// trigger release
	if( keyoff_II ) begin
		cfg_III <= { rrate_II, 1'b1 };
		state_in_III <= RELEASE;
	end
	else begin
		// trigger 1st decay
		if( keyon_II ) begin
			cfg_III <= arate_II;
			state_in_III <= ATTACK;
		end
		else begin : sel_rate
			case ( state_out )
				ATTACK: begin
					if( eg_out==10'd0 ) begin
						state_in_III <= DECAY1;
						cfg_III			 <= rate1_II;
					end
					else begin
						state_in_III <= state_out; // attack
						cfg_III			 <= arate_II;
					end
				end
				DECAY1: begin
					if( eg_out[9:5] >= d1level ) begin
						cfg_III <= rate2_II;
						state_in_III <= DECAY2;
					end
					else begin
						cfg_III	<=	rate1_II;
						state_in_III <= state_out;	// decay1				
					end
				end
				DECAY2: begin
						cfg_III	<=	rate2_II;
						state_in_III <= state_out;	// decay2				
					end
				RELEASE: begin
						cfg_III	<=	{ rrate_II, 1'b1 };
						state_in_III <= state_out;	// release				
					end
			endcase
		end
	end
 
	keyon_III <= keyon_II;
	eg_out_III <= eg_out;
 
	// III		
	state_in_IV <= state_in_III;
	eg_out_IV <= eg_out_III;
	rate_IV <= pre_rate_III[6] ? 6'd63 : pre_rate_III[5:0];
	keyon_IV <= keyon_III;
 
	// IV
	state_in_V	<= state_in_IV;
	rate_V <= rate_IV;
	keyon_V <= keyon_IV;
	eg_out_V <= eg_out_IV;
    if( state_in_IV == ATTACK )
	    casex( rate_IV[5:2] )
		    4'h0: cnt_V <= eg_cnt[13:11]; 
		    4'h1: cnt_V <= eg_cnt[12:10]; 
		    4'h2: cnt_V <= eg_cnt[11: 9]; 
		    4'h3: cnt_V <= eg_cnt[10: 8]; 
		    4'h4: cnt_V <= eg_cnt[ 9: 7]; 
		    4'h5: cnt_V <= eg_cnt[ 8: 6]; 
		    4'h6: cnt_V <= eg_cnt[ 7: 5]; 
		    4'h7: cnt_V <= eg_cnt[ 6: 4]; 
		    4'h8: cnt_V <= eg_cnt[ 5: 3]; 
		    4'h9: cnt_V <= eg_cnt[ 4: 2]; 
		    4'ha: cnt_V <= eg_cnt[ 3: 1]; 
		    default: cnt_V <= eg_cnt[ 2: 0]; 
	    endcase
    else
	    casex( rate_IV[5:2] )
		    4'h0: cnt_V <= eg_cnt[14:12]; 
		    4'h1: cnt_V <= eg_cnt[13:11]; 
		    4'h2: cnt_V <= eg_cnt[12:10]; 
		    4'h3: cnt_V <= eg_cnt[11: 9]; 
		    4'h4: cnt_V <= eg_cnt[10: 8]; 
		    4'h5: cnt_V <= eg_cnt[ 9: 7]; 
		    4'h6: cnt_V <= eg_cnt[ 8: 6]; 
		    4'h7: cnt_V <= eg_cnt[ 7: 5]; 
		    4'h8: cnt_V <= eg_cnt[ 6: 4]; 
		    4'h9: cnt_V <= eg_cnt[ 5: 3]; 
		    4'ha: cnt_V <= eg_cnt[ 4: 2]; 
		    4'hb: cnt_V <= eg_cnt[ 3: 1]; 
		    default: cnt_V <= eg_cnt[ 2: 0]; 
	    endcase
 
	// V
	state_in_VI <= state_in_V;	
	rate_VI <= rate_V[5:1];
	keyon_VI <= keyon_V;
	eg_out_VI <= eg_out_V;
	sum_up <= cnt_V[0] != cnt_out;
	step_VI <= step_V;
	// VI
	if( keyon_VI ) begin
		if( ar_off_VI )
			eg_in <= 10'd0;
		/*else // todo: verify in silicon
			eg_in <= 10'h3ff;*/
	end
	else
	if( state_in_VI == ATTACK ) begin
		if( sum_up && eg_out_VI != 10'd0 )
			if( rate_VI[5:1]==5'd31 ) 
				eg_in <= 10'd0; 
			else
				eg_in <= ar_result;
		else
			eg_in <= eg_out_VI;
	end
	else begin : DECAY_SUM
		if( sum_up ) begin
			if ( eg_out_VI<= (10'd1023-10'd8) ) 
				case( rate_VI[5:2] )
					4'b1100: eg_in <= eg_out_VI + { step_VI, ~step_VI }; // 12
					4'b1101: eg_in <= eg_out_VI + { step_VI, ~step_VI, 1'b0 }; // 13
					4'b1110: eg_in <= eg_out_VI + { step_VI, ~step_VI, 2'b0 }; // 14
					4'b1111: eg_in <= eg_out_VI + 4'd8;// 15
					default: eg_in <= eg_out_VI + { step_VI, 1'b0 };
				endcase
			else eg_in <= 10'h3FF;
		end
		else eg_in <= eg_out_VI;
	end
	// VII
	eg <= sum_eg_tl[11:10] > 2'b0 ? {10{1'b1}} : sum_eg_tl[9:0];
end
 
// Shift registers
 
jt51_sh #( .width(1), .stages(3) ) u_aroffsh(
	.clk	( clk		),
	.din	( ar_off_III),
	.drop	( ar_off_VI	)
);
 
jt51_sh #( .width(2), .stages(2) ) u_kssh(
	.clk	( clk		),
	.din	( ks 		),
	.drop	( ks_III	)
);
 
 
jt51_sh #( .width(10), .stages(6) ) u_tlsh(
	.clk	( clk		),
	.din	( { tl, amsen, ams }	),
	.drop	( { tl_out, amsen_out, ams_out }	)
);
 
jt51_sh #( .width(10), .stages(27) ) u_egsh(
	.clk	( clk		),
	.din	( eg_in		),
	.drop	( eg_out	)
);
 
jt51_sh #( .width(1), .stages(32) ) u_cntsh(
	.clk	( clk		),
	.din	( cnt_V[0]	),
	.drop	( cnt_out	)
);
 
jt51_sh #( .width(2), .stages(31) ) u_statesh(
	.clk	( clk		),
	.din	( state_in_III	),
	.drop	( state_out )
);
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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