mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-11 23:43:09 +00:00
add YM3526
This commit is contained in:
parent
e3e8b4ca55
commit
676202ae97
28
common/Sound/ym3526/jt26.qip
Normal file
28
common/Sound/ym3526/jt26.qip
Normal file
@ -0,0 +1,28 @@
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_acc.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_csr.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_div.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_lfo.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_pm.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg_cnt.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg_comb.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg_ctrl.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg_final.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg_pure.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg_step.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_eg.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_exprom.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_logsin.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_mmr.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_op.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_pg_comb.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_pg_inc.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_pg_sum.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_pg_rhy.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_pg.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_reg.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_sh_rst.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_sh.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_single_acc.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_timers.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl_noise.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtopl.v]
|
||||
253
common/Sound/ym3526/jtopl.v
Normal file
253
common/Sound/ym3526/jtopl.v
Normal file
@ -0,0 +1,253 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 10-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl #(parameter OPL_TYPE=1)
|
||||
(
|
||||
input wire rst, // rst should be at least 6 clk&cen cycles long
|
||||
input wire clk, // CPU clock
|
||||
input wire cen, // optional clock enable, it not needed leave as 1'b1
|
||||
input wire [ 7:0] din,
|
||||
input wire addr,
|
||||
input wire cs_n,
|
||||
input wire wr_n,
|
||||
output wire [ 7:0] dout,
|
||||
output wire irq_n,
|
||||
// combined output
|
||||
output wire signed [15:0] snd,
|
||||
output wire sample
|
||||
);
|
||||
|
||||
//parameter OPL_TYPE=1;
|
||||
|
||||
wire cenop;
|
||||
wire write;
|
||||
wire [ 1:0] group;
|
||||
wire [17:0] slot;
|
||||
wire [ 3:0] trem;
|
||||
|
||||
// Timers
|
||||
wire flag_A, flag_B, flagen_A, flagen_B;
|
||||
wire [ 7:0] value_A;
|
||||
wire [ 7:0] value_B;
|
||||
wire load_A, load_B;
|
||||
wire clr_flag_A, clr_flag_B;
|
||||
wire overflow_A;
|
||||
wire zero; // Single-clock pulse at the begginig of s1_enters
|
||||
|
||||
// Phase
|
||||
wire [ 9:0] fnum_I;
|
||||
wire [ 2:0] block_I;
|
||||
wire [ 3:0] mul_II;
|
||||
wire [ 9:0] phase_IV;
|
||||
wire pg_rst_II;
|
||||
wire viben_I;
|
||||
wire [ 2:0] vib_cnt;
|
||||
// envelope configuration
|
||||
wire en_sus_I; // enable sustain
|
||||
wire [ 3:0] keycode_II;
|
||||
wire [ 3:0] arate_I; // attack rate
|
||||
wire [ 3:0] drate_I; // decay rate
|
||||
wire [ 3:0] rrate_I; // release rate
|
||||
wire [ 3:0] sl_I; // sustain level
|
||||
wire ksr_II; // key scale rate - affects rates
|
||||
wire [ 1:0] ksl_IV; // key scale level - affects amplitude
|
||||
// envelope operation
|
||||
wire keyon_I;
|
||||
wire eg_stop;
|
||||
// envelope number
|
||||
wire amen_IV;
|
||||
wire [ 5:0] tl_IV;
|
||||
wire [ 9:0] eg_V;
|
||||
// Global values
|
||||
wire am_dep, vib_dep, rhy_en;
|
||||
// Operator
|
||||
wire [ 2:0] fb_I;
|
||||
wire [ 1:0] wavsel_I;
|
||||
wire op, con_I, op_out, con_out;
|
||||
|
||||
wire signed [12:0] op_result;
|
||||
|
||||
assign write = !cs_n && !wr_n;
|
||||
assign dout = { ~irq_n, flag_A, flag_B, 5'd6 };
|
||||
assign eg_stop = 0;
|
||||
assign sample = zero;
|
||||
|
||||
jtopl_mmr #(.OPL_TYPE(OPL_TYPE)) u_mmr(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ), // external clock enable
|
||||
.cenop ( cenop ), // internal clock enable
|
||||
.din ( din ),
|
||||
.write ( write ),
|
||||
.addr ( addr ),
|
||||
.zero ( zero ),
|
||||
.group ( group ),
|
||||
.op ( op ),
|
||||
.slot ( slot ),
|
||||
.rhy_en ( rhy_en ),
|
||||
// Timers
|
||||
.value_A ( value_A ),
|
||||
.value_B ( value_B ),
|
||||
.load_A ( load_A ),
|
||||
.load_B ( load_B ),
|
||||
.flagen_A ( flagen_A ),
|
||||
.flagen_B ( flagen_B ),
|
||||
.clr_flag_A ( clr_flag_A ),
|
||||
.clr_flag_B ( clr_flag_B ),
|
||||
.flag_A ( flag_A ),
|
||||
.overflow_A ( overflow_A ),
|
||||
// Phase Generator
|
||||
.fnum_I ( fnum_I ),
|
||||
.block_I ( block_I ),
|
||||
.mul_II ( mul_II ),
|
||||
// Operator
|
||||
.wavsel_I ( wavsel_I ),
|
||||
// Envelope Generator
|
||||
.keyon_I ( keyon_I ),
|
||||
.en_sus_I ( en_sus_I ),
|
||||
.arate_I ( arate_I ),
|
||||
.drate_I ( drate_I ),
|
||||
.rrate_I ( rrate_I ),
|
||||
.sl_I ( sl_I ),
|
||||
.ks_II ( ksr_II ),
|
||||
.tl_IV ( tl_IV ),
|
||||
.ksl_IV ( ksl_IV ),
|
||||
.amen_IV ( amen_IV ),
|
||||
.viben_I ( viben_I ),
|
||||
// Global Values
|
||||
.am_dep ( am_dep ),
|
||||
.vib_dep ( vib_dep ),
|
||||
// Timbre
|
||||
.fb_I ( fb_I ),
|
||||
.con_I ( con_I )
|
||||
);
|
||||
|
||||
jtopl_timers u_timers(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
.zero ( zero ),
|
||||
.value_A ( value_A ),
|
||||
.value_B ( value_B ),
|
||||
.load_A ( load_A ),
|
||||
.load_B ( load_B ),
|
||||
.flagen_A ( flagen_A ),
|
||||
.flagen_B ( flagen_B ),
|
||||
.clr_flag_A ( clr_flag_A ),
|
||||
.clr_flag_B ( clr_flag_B ),
|
||||
.flag_A ( flag_A ),
|
||||
.flag_B ( flag_B ),
|
||||
.overflow_A ( overflow_A ),
|
||||
.irq_n ( irq_n )
|
||||
);
|
||||
|
||||
jtopl_lfo u_lfo(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
.slot ( slot ),
|
||||
.vib_cnt ( vib_cnt ),
|
||||
.trem ( trem )
|
||||
);
|
||||
|
||||
jtopl_pg u_pg(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
.slot ( slot ),
|
||||
.rhy_en ( rhy_en ),
|
||||
// Channel frequency
|
||||
.fnum_I ( fnum_I ),
|
||||
.block_I ( block_I ),
|
||||
// Operator multiplying
|
||||
.mul_II ( mul_II ),
|
||||
// phase modulation from LFO (vibrato at 6.4Hz)
|
||||
.vib_cnt ( vib_cnt ),
|
||||
.vib_dep ( vib_dep ),
|
||||
.viben_I ( viben_I ),
|
||||
// phase operation
|
||||
.pg_rst_II ( pg_rst_II ),
|
||||
|
||||
.keycode_II ( keycode_II ),
|
||||
.phase_IV ( phase_IV )
|
||||
);
|
||||
|
||||
jtopl_eg u_eg(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
.zero ( zero ),
|
||||
.eg_stop ( eg_stop ),
|
||||
// envelope configuration
|
||||
.en_sus_I ( en_sus_I ), // enable sustain
|
||||
.keycode_II ( keycode_II ),
|
||||
.arate_I ( arate_I ), // attack rate
|
||||
.drate_I ( drate_I ), // decay rate
|
||||
.rrate_I ( rrate_I ), // release rate
|
||||
.sl_I ( sl_I ), // sustain level
|
||||
.ksr_II ( ksr_II ), // key scale
|
||||
// envelope operation
|
||||
.keyon_I ( keyon_I ),
|
||||
// envelope number
|
||||
.fnum_I ( fnum_I ),
|
||||
.block_I ( block_I ),
|
||||
.lfo_mod ( trem ),
|
||||
.amsen_IV ( amen_IV ),
|
||||
.ams_IV ( am_dep ),
|
||||
.tl_IV ( tl_IV ),
|
||||
.ksl_IV ( ksl_IV ),
|
||||
.eg_V ( eg_V ),
|
||||
.pg_rst_II ( pg_rst_II )
|
||||
);
|
||||
|
||||
jtopl_op #(.OPL_TYPE(OPL_TYPE)) u_op(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
|
||||
// location of current operator
|
||||
.group ( group ),
|
||||
.op ( op ),
|
||||
.zero ( zero ),
|
||||
|
||||
.pg_phase_I ( phase_IV ),
|
||||
.eg_atten_II( eg_V ), // output from envelope generator
|
||||
.fb_I ( fb_I ), // voice feedback
|
||||
.wavsel_I ( wavsel_I ), // sine mask (OPL2)
|
||||
|
||||
.con_I ( con_I ),
|
||||
.op_result ( op_result ),
|
||||
.op_out ( op_out ),
|
||||
.con_out ( con_out )
|
||||
);
|
||||
|
||||
jtopl_acc u_acc(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
.zero ( zero ),
|
||||
.op_result ( op_result ),
|
||||
.op ( op_out ),
|
||||
.con ( con_out ),
|
||||
.snd ( snd )
|
||||
);
|
||||
|
||||
endmodule
|
||||
52
common/Sound/ym3526/jtopl2.v
Normal file
52
common/Sound/ym3526/jtopl2.v
Normal file
@ -0,0 +1,52 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 10-10-2021
|
||||
|
||||
*/
|
||||
|
||||
module jtopl2(
|
||||
input wire rst, // rst should be at least 6 clk&cen cycles long
|
||||
input wire clk, // CPU clock
|
||||
input wire cen, // optional clock enable, it not needed leave as 1'b1
|
||||
input wire [ 7:0] din,
|
||||
input wire addr,
|
||||
input wire cs_n,
|
||||
input wire wr_n,
|
||||
output wire [ 7:0] dout,
|
||||
output wire irq_n,
|
||||
// combined output
|
||||
output wire signed [15:0] snd,
|
||||
output wire sample
|
||||
);
|
||||
|
||||
`define JTOPL2
|
||||
jtopl #(.OPL_TYPE(2)) u_base(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( din ),
|
||||
.addr ( addr ),
|
||||
.cs_n ( cs_n ),
|
||||
.wr_n ( wr_n ),
|
||||
.dout ( dout ),
|
||||
.irq_n ( irq_n ),
|
||||
.snd ( snd ),
|
||||
.sample ( sample )
|
||||
);
|
||||
|
||||
endmodule
|
||||
48
common/Sound/ym3526/jtopl_acc.v
Normal file
48
common/Sound/ym3526/jtopl_acc.v
Normal file
@ -0,0 +1,48 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 20-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_acc(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cenop,
|
||||
input wire signed [12:0] op_result,
|
||||
input wire zero,
|
||||
input wire op, // 0 for modulator operators
|
||||
input wire con, // 0 for modulated connection
|
||||
output wire signed [15:0] snd
|
||||
);
|
||||
|
||||
wire sum_en;
|
||||
|
||||
assign sum_en = op | con;
|
||||
|
||||
// Continuous output
|
||||
jtopl_single_acc u_acc(
|
||||
.clk ( clk ),
|
||||
.cenop ( cenop ),
|
||||
.op_result ( op_result ),
|
||||
.sum_en ( sum_en ),
|
||||
.zero ( zero ),
|
||||
.snd ( snd )
|
||||
);
|
||||
|
||||
endmodule
|
||||
77
common/Sound/ym3526/jtopl_csr.v
Normal file
77
common/Sound/ym3526/jtopl_csr.v
Normal file
@ -0,0 +1,77 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_csr #(
|
||||
parameter LEN=18, W=34
|
||||
) ( // Circular Shift Register + input mux
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
input wire [ 7:0] din,
|
||||
output wire [W-1:0] shift_out,
|
||||
|
||||
input wire up_mult,
|
||||
input wire up_ksl_tl,
|
||||
input wire up_ar_dr,
|
||||
input wire up_sl_rr,
|
||||
input wire up_wav,
|
||||
input wire update_op_I,
|
||||
input wire update_op_II,
|
||||
input wire update_op_IV
|
||||
);
|
||||
|
||||
|
||||
wire [W-1:0] regop_in;
|
||||
|
||||
jtopl_sh_rst #(.width(W),.stages(LEN)) u_regch(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.rst ( rst ),
|
||||
.din ( regop_in ),
|
||||
.drop ( shift_out )
|
||||
);
|
||||
|
||||
wire up_mult_I = up_mult & update_op_I;
|
||||
wire up_mult_II = up_mult & update_op_II;
|
||||
wire up_mult_IV = up_mult & update_op_IV;
|
||||
wire up_ksl_tl_IV = up_ksl_tl & update_op_IV;
|
||||
wire up_ar_dr_op = up_ar_dr & update_op_I;
|
||||
wire up_sl_rr_op = up_sl_rr & update_op_I;
|
||||
wire up_wav_I = up_wav & update_op_I;
|
||||
|
||||
assign regop_in[31:0] = { // 4 bytes:
|
||||
up_mult_IV ? din[7] : shift_out[31], // AM enable
|
||||
up_mult_I ? din[6:5] : shift_out[30:29], // Vib enable, EG type, KSR
|
||||
up_mult_II ? din[4:0] : shift_out[28:24], // KSR + Mult
|
||||
|
||||
up_ksl_tl_IV? din : shift_out[23:16], // KSL + TL
|
||||
|
||||
up_ar_dr_op ? din : shift_out[15: 8],
|
||||
|
||||
up_sl_rr_op ? din : shift_out[ 7: 0]
|
||||
};
|
||||
|
||||
// `ifdef JTOPL2
|
||||
// assign regop_in[33:32] = up_wav_I ? din[1:0] : shift_out[33:32];
|
||||
// `endif
|
||||
|
||||
endmodule // jtopl_reg
|
||||
48
common/Sound/ym3526/jtopl_div.v
Normal file
48
common/Sound/ym3526/jtopl_div.v
Normal file
@ -0,0 +1,48 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 10-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_div #(parameter OPL_TYPE=1)
|
||||
(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
output reg cenop // clock enable at operator rate
|
||||
);
|
||||
|
||||
//parameter OPL_TYPE=1;
|
||||
|
||||
localparam W = 2; // OPL_TYPE==2 ? 1 : 2;
|
||||
|
||||
reg [W-1:0] cnt;
|
||||
|
||||
`ifdef SIMULATION
|
||||
initial cnt={W{1'b0}};
|
||||
`endif
|
||||
|
||||
always @(posedge clk) if(cen) begin
|
||||
cnt <= cnt+1'd1;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
cenop <= cen && (&cnt);
|
||||
end
|
||||
|
||||
endmodule
|
||||
203
common/Sound/ym3526/jtopl_eg.v
Normal file
203
common/Sound/ym3526/jtopl_eg.v
Normal file
@ -0,0 +1,203 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg (
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cenop,
|
||||
input wire zero,
|
||||
input wire eg_stop,
|
||||
// envelope configuration
|
||||
input wire en_sus_I, // enable sustain
|
||||
input wire [3:0] keycode_II,
|
||||
input wire [3:0] arate_I, // attack rate
|
||||
input wire [3:0] drate_I, // decay rate
|
||||
input wire [3:0] rrate_I, // release rate
|
||||
input wire [3:0] sl_I, // sustain level
|
||||
input wire ksr_II, // key scale
|
||||
// envelope operation
|
||||
input wire keyon_I,
|
||||
// envelope number
|
||||
input wire [9:0] fnum_I,
|
||||
input wire [2:0] block_I,
|
||||
input wire [3:0] lfo_mod,
|
||||
input wire amsen_IV,
|
||||
input wire ams_IV,
|
||||
input wire [5:0] tl_IV,
|
||||
input wire [1:0] ksl_IV,
|
||||
|
||||
output reg [9:0] eg_V,
|
||||
output reg pg_rst_II
|
||||
);
|
||||
|
||||
parameter SLOTS=18;
|
||||
|
||||
wire [14:0] eg_cnt;
|
||||
|
||||
jtopl_eg_cnt u_egcnt(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cenop & ~eg_stop ),
|
||||
.zero ( zero ),
|
||||
.eg_cnt ( eg_cnt)
|
||||
);
|
||||
|
||||
wire keyon_last_I;
|
||||
wire keyon_now_I = !keyon_last_I && keyon_I;
|
||||
wire keyoff_now_I = keyon_last_I && !keyon_I;
|
||||
|
||||
wire cnt_in_II, cnt_lsb_II, step_II, pg_rst_I;
|
||||
|
||||
wire [2:0] state_in_I, state_next_I;
|
||||
|
||||
reg attack_II, attack_III;
|
||||
wire [4:0] base_rate_I;
|
||||
reg [4:0] base_rate_II;
|
||||
wire [5:0] rate_out_II;
|
||||
reg [5:1] rate_in_III;
|
||||
reg step_III;
|
||||
wire sum_out_II;
|
||||
reg sum_in_III;
|
||||
|
||||
wire [9:0] eg_in_I, pure_eg_out_III, eg_next_III, eg_out_IV;
|
||||
reg [9:0] eg_in_II, eg_in_III, eg_in_IV;
|
||||
reg [3:0] keycode_III, keycode_IV;
|
||||
wire [3:0] fnum_IV;
|
||||
wire [2:0] block_IV;
|
||||
|
||||
|
||||
jtopl_eg_comb u_comb(
|
||||
///////////////////////////////////
|
||||
// I
|
||||
.keyon_now ( keyon_now_I ),
|
||||
.keyoff_now ( keyoff_now_I ),
|
||||
.state_in ( state_in_I ),
|
||||
.eg_in ( eg_in_I ),
|
||||
// envelope configuration
|
||||
.en_sus ( en_sus_I ),
|
||||
.arate ( arate_I ), // attack rate
|
||||
.drate ( drate_I ), // decay rate
|
||||
.rrate ( rrate_I ),
|
||||
.sl ( sl_I ), // sustain level
|
||||
|
||||
.base_rate ( base_rate_I ),
|
||||
.state_next ( state_next_I ),
|
||||
.pg_rst ( pg_rst_I ),
|
||||
///////////////////////////////////
|
||||
// II
|
||||
.step_attack ( attack_II ),
|
||||
.step_rate_in ( base_rate_II ),
|
||||
.keycode ( keycode_II ),
|
||||
.eg_cnt ( eg_cnt ),
|
||||
.cnt_in ( cnt_in_II ),
|
||||
.ksr ( ksr_II ),
|
||||
.cnt_lsb ( cnt_lsb_II ),
|
||||
.step ( step_II ),
|
||||
.step_rate_out ( rate_out_II ),
|
||||
.sum_up_out ( sum_out_II ),
|
||||
///////////////////////////////////
|
||||
// III
|
||||
.pure_attack ( attack_III ),
|
||||
.pure_step ( step_III ),
|
||||
.pure_rate ( rate_in_III[5:1] ),
|
||||
.pure_eg_in ( eg_in_III ),
|
||||
.pure_eg_out ( pure_eg_out_III ),
|
||||
.sum_up_in ( sum_in_III ),
|
||||
///////////////////////////////////
|
||||
// IV
|
||||
.fnum ( fnum_IV ),
|
||||
.block ( block_IV ),
|
||||
.lfo_mod ( lfo_mod ),
|
||||
.amsen ( amsen_IV ),
|
||||
.ams ( ams_IV ),
|
||||
.ksl ( ksl_IV ),
|
||||
.tl ( tl_IV ),
|
||||
.final_keycode ( keycode_IV ),
|
||||
.final_eg_in ( eg_in_IV ),
|
||||
.final_eg_out ( eg_out_IV )
|
||||
);
|
||||
|
||||
always @(posedge clk) if(cenop) begin
|
||||
eg_in_II <= eg_in_I;
|
||||
attack_II <= state_next_I[0];
|
||||
base_rate_II<= base_rate_I;
|
||||
pg_rst_II <= pg_rst_I;
|
||||
|
||||
eg_in_III <= eg_in_II;
|
||||
attack_III <= attack_II;
|
||||
rate_in_III <= rate_out_II[5:1];
|
||||
step_III <= step_II;
|
||||
sum_in_III <= sum_out_II;
|
||||
|
||||
eg_in_IV <= pure_eg_out_III;
|
||||
eg_V <= eg_out_IV;
|
||||
|
||||
keycode_III <= keycode_II;
|
||||
keycode_IV <= keycode_III;
|
||||
end
|
||||
|
||||
jtopl_sh #( .width(1), .stages(SLOTS) ) u_cntsh(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( cnt_lsb_II),
|
||||
.drop ( cnt_in_II )
|
||||
);
|
||||
|
||||
jtopl_sh #( .width(4), .stages(3) ) u_fnumsh(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( fnum_I[9:6] ),
|
||||
.drop ( fnum_IV )
|
||||
);
|
||||
|
||||
jtopl_sh #( .width(3), .stages(3) ) u_blocksh(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( block_I ),
|
||||
.drop ( block_IV )
|
||||
);
|
||||
|
||||
jtopl_sh_rst #( .width(10), .stages(SLOTS-3), .rstval(1'b1) ) u_egsh(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.rst ( rst ),
|
||||
.din ( eg_in_IV ),
|
||||
.drop ( eg_in_I )
|
||||
);
|
||||
|
||||
jtopl_sh_rst #( .width(3), .stages(SLOTS), .rstval(1'b1) ) u_egstate(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.rst ( rst ),
|
||||
.din ( state_next_I ),
|
||||
.drop ( state_in_I )
|
||||
);
|
||||
|
||||
jtopl_sh_rst #( .width(1), .stages(SLOTS), .rstval(1'b0) ) u_konsh(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.rst ( rst ),
|
||||
.din ( keyon_I ),
|
||||
.drop ( keyon_last_I )
|
||||
);
|
||||
|
||||
|
||||
endmodule // jtopl_eg
|
||||
44
common/Sound/ym3526/jtopl_eg_cnt.v
Normal file
44
common/Sound/ym3526/jtopl_eg_cnt.v
Normal file
@ -0,0 +1,44 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg_cnt(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
input wire zero,
|
||||
output reg [14:0] eg_cnt
|
||||
);
|
||||
|
||||
always @(posedge clk, posedge rst) begin : envelope_counter
|
||||
if( rst ) begin
|
||||
eg_cnt <=15'd0;
|
||||
end
|
||||
else begin
|
||||
if( zero && cen ) begin
|
||||
// envelope counter increases at each zero input
|
||||
// This is different from OPN/M where it increased
|
||||
// once every three zero inputs
|
||||
eg_cnt <= eg_cnt + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
131
common/Sound/ym3526/jtopl_eg_comb.v
Normal file
131
common/Sound/ym3526/jtopl_eg_comb.v
Normal file
@ -0,0 +1,131 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg_comb(
|
||||
input wire keyon_now,
|
||||
input wire keyoff_now,
|
||||
input wire [ 2:0] state_in,
|
||||
input wire [ 9:0] eg_in,
|
||||
// envelope configuration
|
||||
input wire en_sus, // enable sustain
|
||||
input wire [ 3:0] arate, // attack rate
|
||||
input wire [ 3:0] drate, // decay rate
|
||||
input wire [ 3:0] rrate,
|
||||
input wire [ 3:0] sl, // sustain level
|
||||
|
||||
output wire [ 4:0] base_rate,
|
||||
output wire [ 2:0] state_next,
|
||||
output wire pg_rst,
|
||||
///////////////////////////////////
|
||||
// II
|
||||
input wire step_attack,
|
||||
input wire [ 4:0] step_rate_in,
|
||||
input wire [ 3:0] keycode,
|
||||
input wire [14:0] eg_cnt,
|
||||
input wire cnt_in,
|
||||
input wire ksr,
|
||||
output wire cnt_lsb,
|
||||
output wire step,
|
||||
output wire [ 5:0] step_rate_out,
|
||||
output wire sum_up_out,
|
||||
///////////////////////////////////
|
||||
// III
|
||||
input wire pure_attack,
|
||||
input wire pure_step,
|
||||
input wire [ 5:1] pure_rate,
|
||||
input wire [ 9:0] pure_eg_in,
|
||||
output wire [ 9:0] pure_eg_out,
|
||||
input wire sum_up_in,
|
||||
///////////////////////////////////
|
||||
// IV
|
||||
input wire [ 3:0] lfo_mod,
|
||||
input wire [ 3:0] fnum,
|
||||
input wire [ 2:0] block,
|
||||
input wire amsen,
|
||||
input wire ams,
|
||||
input wire [ 5:0] tl,
|
||||
input wire [ 1:0] ksl,
|
||||
input wire [ 3:0] final_keycode,
|
||||
input wire [ 9:0] final_eg_in,
|
||||
output wire [ 9:0] final_eg_out
|
||||
);
|
||||
|
||||
// I
|
||||
jtopl_eg_ctrl u_ctrl(
|
||||
.keyon_now ( keyon_now ),
|
||||
.keyoff_now ( keyoff_now ),
|
||||
.state_in ( state_in ),
|
||||
.eg ( eg_in ),
|
||||
// envelope configuration
|
||||
.en_sus ( en_sus ),
|
||||
.arate ( arate ), // attack rate
|
||||
.drate ( drate ), // decay rate
|
||||
.rrate ( rrate ),
|
||||
.sl ( sl ), // sustain level
|
||||
|
||||
.base_rate ( base_rate ),
|
||||
.state_next ( state_next ),
|
||||
.pg_rst ( pg_rst )
|
||||
);
|
||||
|
||||
// II
|
||||
|
||||
jtopl_eg_step u_step(
|
||||
.attack ( step_attack ),
|
||||
.base_rate ( step_rate_in ),
|
||||
.keycode ( keycode ),
|
||||
.eg_cnt ( eg_cnt ),
|
||||
.cnt_in ( cnt_in ),
|
||||
.ksr ( ksr ),
|
||||
.cnt_lsb ( cnt_lsb ),
|
||||
.step ( step ),
|
||||
.rate ( step_rate_out ),
|
||||
.sum_up ( sum_up_out )
|
||||
);
|
||||
|
||||
// III
|
||||
|
||||
wire [9:0] egin, egout;
|
||||
jtopl_eg_pure u_pure(
|
||||
.attack ( pure_attack ),
|
||||
.step ( pure_step ),
|
||||
.rate ( pure_rate ),
|
||||
.eg_in ( pure_eg_in ),
|
||||
.eg_pure( pure_eg_out ),
|
||||
.sum_up ( sum_up_in )
|
||||
);
|
||||
|
||||
// IV
|
||||
|
||||
jtopl_eg_final u_final(
|
||||
.fnum ( fnum ),
|
||||
.block ( block ),
|
||||
.lfo_mod ( lfo_mod ),
|
||||
.amsen ( amsen ),
|
||||
.ams ( ams ),
|
||||
.tl ( tl ),
|
||||
.ksl ( ksl ),
|
||||
.keycode ( final_keycode ),
|
||||
.eg_pure_in ( final_eg_in ),
|
||||
.eg_limited ( final_eg_out )
|
||||
);
|
||||
|
||||
endmodule // jtopl_eg_comb
|
||||
87
common/Sound/ym3526/jtopl_eg_ctrl.v
Normal file
87
common/Sound/ym3526/jtopl_eg_ctrl.v
Normal file
@ -0,0 +1,87 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg_ctrl(
|
||||
input wire keyon_now,
|
||||
input wire keyoff_now,
|
||||
input wire [2:0] state_in,
|
||||
input wire [9:0] eg,
|
||||
// envelope configuration
|
||||
input wire en_sus, // enable sustain
|
||||
input wire [3:0] arate, // attack rate
|
||||
input wire [3:0] drate, // decay rate
|
||||
input wire [3:0] rrate,
|
||||
input wire [3:0] sl, // sustain level
|
||||
|
||||
output reg [4:0] base_rate,
|
||||
output reg [2:0] state_next,
|
||||
output reg pg_rst
|
||||
);
|
||||
|
||||
localparam ATTACK = 3'b001,
|
||||
DECAY = 3'b010,
|
||||
HOLD = 3'b100,
|
||||
RELEASE= 3'b000; // default state is release
|
||||
|
||||
// wire is_decaying = state_in[1] | state_in[2];
|
||||
|
||||
wire [4:0] sustain = { &sl, sl}; //93dB if sl==4'hF
|
||||
|
||||
always @(*) begin
|
||||
pg_rst = keyon_now;
|
||||
end
|
||||
|
||||
always @(*)
|
||||
casez ( { keyoff_now, keyon_now, state_in} )
|
||||
5'b01_???: begin // key on
|
||||
base_rate = {arate,1'b0};
|
||||
state_next = ATTACK;
|
||||
end
|
||||
{2'b00, ATTACK}:
|
||||
if( eg==10'd0 ) begin
|
||||
base_rate = {drate,1'b0};
|
||||
state_next = DECAY;
|
||||
end
|
||||
else begin
|
||||
base_rate = {arate,1'b0};
|
||||
state_next = ATTACK;
|
||||
end
|
||||
{2'b00, DECAY}: begin
|
||||
if( eg[9:5] >= sustain ) begin
|
||||
base_rate = en_sus ? 5'd0 : {rrate,1'b0};
|
||||
state_next = en_sus ? HOLD : RELEASE;
|
||||
end else begin
|
||||
base_rate = {drate,1'b0};
|
||||
state_next = DECAY;
|
||||
end
|
||||
end
|
||||
{2'b00, HOLD}: begin
|
||||
base_rate = 5'd0;
|
||||
state_next = HOLD;
|
||||
end
|
||||
default: begin // RELEASE, note that keyoff_now==1 will enter this state too
|
||||
base_rate = {rrate,1'b1};
|
||||
state_next = RELEASE; // release
|
||||
end
|
||||
endcase
|
||||
|
||||
|
||||
endmodule // jtopl_eg_ctrl
|
||||
70
common/Sound/ym3526/jtopl_eg_final.v
Normal file
70
common/Sound/ym3526/jtopl_eg_final.v
Normal file
@ -0,0 +1,70 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg_final(
|
||||
input wire [3:0] lfo_mod,
|
||||
input wire [3:0] fnum,
|
||||
input wire [2:0] block,
|
||||
input wire amsen,
|
||||
input wire ams,
|
||||
input wire [5:0] tl,
|
||||
input wire [1:0] ksl, // level damped by pitch
|
||||
input wire [3:0] keycode,
|
||||
input wire [9:0] eg_pure_in,
|
||||
output reg [9:0] eg_limited
|
||||
);
|
||||
|
||||
reg [ 5:0] am_final;
|
||||
reg [11:0] sum_eg_tl;
|
||||
reg [11:0] sum_eg_tl_am;
|
||||
reg [ 8:0] ksl_dB;
|
||||
reg [ 6:0] ksl_lut[0:15];
|
||||
reg [ 7:0] ksl_base;
|
||||
|
||||
always @(*) begin
|
||||
ksl_base = {1'b0, ksl_lut[fnum]}- { 1'b0, 4'd8-{1'b0,block}, 3'b0 };
|
||||
if( ksl_base[7] || ksl==2'b0 ) begin
|
||||
ksl_dB = 9'd0;
|
||||
end else begin
|
||||
ksl_dB = {ksl_base[6:0],2'b0} >> ~ksl;
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
am_final = amsen ? ( ams ? {lfo_mod, 2'b0} : {2'b0, lfo_mod} ) : 6'd0;
|
||||
sum_eg_tl = { 2'b0, tl, 3'd0 } +
|
||||
{ 1'b0, ksl_dB, 1'd0 } +
|
||||
{ 1'b0, eg_pure_in}; // leading zeros needed to compute correctly
|
||||
sum_eg_tl_am = sum_eg_tl + { 5'd0, am_final };
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
eg_limited = sum_eg_tl_am[11:10]==2'd0 ? sum_eg_tl_am[9:0] : 10'h3ff;
|
||||
end
|
||||
|
||||
initial begin
|
||||
ksl_lut[ 0] = 7'd00; ksl_lut[ 1] = 7'd32; ksl_lut[ 2] = 7'd40; ksl_lut[ 3] = 7'd45;
|
||||
ksl_lut[ 4] = 7'd48; ksl_lut[ 5] = 7'd51; ksl_lut[ 6] = 7'd53; ksl_lut[ 7] = 7'd55;
|
||||
ksl_lut[ 8] = 7'd56; ksl_lut[ 9] = 7'd58; ksl_lut[10] = 7'd59; ksl_lut[11] = 7'd60;
|
||||
ksl_lut[12] = 7'd61; ksl_lut[13] = 7'd62; ksl_lut[14] = 7'd63; ksl_lut[15] = 7'd64;
|
||||
end
|
||||
|
||||
endmodule
|
||||
81
common/Sound/ym3526/jtopl_eg_pure.v
Normal file
81
common/Sound/ym3526/jtopl_eg_pure.v
Normal file
@ -0,0 +1,81 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg_pure(
|
||||
input wire attack,
|
||||
input wire step,
|
||||
input wire [ 5:1] rate,
|
||||
input wire [ 9:0] eg_in,
|
||||
input wire sum_up,
|
||||
output reg [9:0] eg_pure
|
||||
);
|
||||
|
||||
reg [ 3:0] dr_sum;
|
||||
reg [ 9:0] dr_adj;
|
||||
reg [10:0] dr_result;
|
||||
|
||||
always @(*) begin : dr_calculation
|
||||
case( rate[5:2] )
|
||||
4'b1100: dr_sum = { 2'b0, step, ~step }; // 12
|
||||
4'b1101: dr_sum = { 1'b0, step, ~step, 1'b0 }; // 13
|
||||
4'b1110: dr_sum = { step, ~step, 2'b0 }; // 14
|
||||
4'b1111: dr_sum = 4'd8;// 15
|
||||
default: dr_sum = { 2'b0, step, 1'b0 };
|
||||
endcase
|
||||
// Decay rate attenuation is multiplied by 4 for SSG operation
|
||||
dr_adj = {6'd0, dr_sum};
|
||||
dr_result = dr_adj + eg_in;
|
||||
end
|
||||
|
||||
reg [ 7:0] ar_sum0;
|
||||
reg [ 8:0] ar_sum1;
|
||||
reg [10:0] ar_result;
|
||||
reg [ 9:0] ar_sum;
|
||||
|
||||
always @(*) begin : ar_calculation
|
||||
casez( rate[5:2] )
|
||||
default: ar_sum0 = {2'd0, eg_in[9:4]};
|
||||
4'b1101: ar_sum0 = {1'd0, eg_in[9:3]};
|
||||
4'b111?: ar_sum0 = eg_in[9:2];
|
||||
endcase
|
||||
ar_sum1 = ar_sum0+9'd1;
|
||||
if( rate[5:4] == 2'b11 )
|
||||
ar_sum = step ? { ar_sum1, 1'b0 } : { 1'b0, ar_sum1 };
|
||||
else
|
||||
ar_sum = step ? { 1'b0, ar_sum1 } : 10'd0;
|
||||
ar_result = eg_in-ar_sum;
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// rate not used below this point
|
||||
reg [9:0] eg_pre_fastar; // pre fast attack rate
|
||||
always @(*) begin
|
||||
if(sum_up) begin
|
||||
if( attack )
|
||||
eg_pre_fastar = ar_result[10] ? 10'd0: ar_result[9:0];
|
||||
else
|
||||
eg_pre_fastar = dr_result[10] ? 10'h3FF : dr_result[9:0];
|
||||
end
|
||||
else eg_pre_fastar = eg_in;
|
||||
eg_pure = (attack&rate[5:1]==5'h1F) ? 10'd0 : eg_pre_fastar;
|
||||
end
|
||||
|
||||
endmodule
|
||||
108
common/Sound/ym3526/jtopl_eg_step.v
Normal file
108
common/Sound/ym3526/jtopl_eg_step.v
Normal file
@ -0,0 +1,108 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 17-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_eg_step(
|
||||
input wire attack,
|
||||
input wire [ 4:0] base_rate,
|
||||
input wire [ 3:0] keycode,
|
||||
input wire [14:0] eg_cnt,
|
||||
input wire cnt_in,
|
||||
input wire ksr,
|
||||
output wire cnt_lsb,
|
||||
output reg step,
|
||||
output reg [ 5:0] rate,
|
||||
output reg sum_up
|
||||
);
|
||||
|
||||
reg [6:0] pre_rate;
|
||||
|
||||
always @(*) begin : pre_rate_calc
|
||||
if( base_rate == 5'd0 )
|
||||
pre_rate = 7'd0;
|
||||
else
|
||||
pre_rate = { 1'b0, base_rate, 1'b0 } + (ksr ?
|
||||
{ 3'b0, keycode }:
|
||||
{ 5'b0, keycode[3:2] });
|
||||
end
|
||||
|
||||
always @(*)
|
||||
rate = pre_rate>=7'b1111_00 ? 6'b1111_11 : pre_rate[5:0];
|
||||
|
||||
reg [2:0] cnt;
|
||||
|
||||
reg [4:0] mux_sel;
|
||||
always @(*) begin
|
||||
mux_sel = attack ? (rate[5:2]+4'd1): {1'b0,rate[5:2]};
|
||||
end
|
||||
|
||||
always @(*)
|
||||
case( mux_sel )
|
||||
5'h0: cnt = eg_cnt[14:12];
|
||||
5'h1: cnt = eg_cnt[13:11];
|
||||
5'h2: cnt = eg_cnt[12:10];
|
||||
5'h3: cnt = eg_cnt[11: 9];
|
||||
5'h4: cnt = eg_cnt[10: 8];
|
||||
5'h5: cnt = eg_cnt[ 9: 7];
|
||||
5'h6: cnt = eg_cnt[ 8: 6];
|
||||
5'h7: cnt = eg_cnt[ 7: 5];
|
||||
5'h8: cnt = eg_cnt[ 6: 4];
|
||||
5'h9: cnt = eg_cnt[ 5: 3];
|
||||
5'ha: cnt = eg_cnt[ 4: 2];
|
||||
5'hb: cnt = eg_cnt[ 3: 1];
|
||||
default: cnt = eg_cnt[ 2: 0];
|
||||
endcase
|
||||
|
||||
////////////////////////////////
|
||||
reg [7:0] step_idx;
|
||||
|
||||
always @(*) begin : rate_step
|
||||
if( rate[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x
|
||||
if( rate[5:2]==4'hf && attack)
|
||||
step_idx = 8'b11111111; // Maximum attack speed, rates 60&61
|
||||
else
|
||||
case( rate[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[5:2]==4'd0 && !attack)
|
||||
step_idx = 8'b11111110; // limit slowest decay rate
|
||||
else
|
||||
case( rate[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 of zero keeps the level still
|
||||
step = rate[5:1]==5'd0 ? 1'b0 : step_idx[ cnt ];
|
||||
end
|
||||
|
||||
assign cnt_lsb = cnt[0];
|
||||
always @(*) begin
|
||||
sum_up = cnt[0] != cnt_in;
|
||||
end
|
||||
|
||||
endmodule // eg_step
|
||||
305
common/Sound/ym3526/jtopl_exprom.v
Normal file
305
common/Sound/ym3526/jtopl_exprom.v
Normal file
@ -0,0 +1,305 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 20-6-2020
|
||||
|
||||
*/
|
||||
|
||||
// Yamaha used the same table for OPN, OPM and OPL
|
||||
// Originally written in more compact way that required some logic to decompress
|
||||
// Not really worth compressing when the target is an FPGA as one BRAM will be
|
||||
// used in either case. So it's better to leave it uncompress and save the
|
||||
// decoding logic
|
||||
|
||||
// altera message_off 10030
|
||||
|
||||
module jtopl_exprom
|
||||
(
|
||||
input wire [7:0] addr,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
output reg [9:0] exp
|
||||
);
|
||||
|
||||
reg [9:0] explut_jt51[255:0];
|
||||
initial
|
||||
begin
|
||||
explut_jt51[8'd000] = 10'd1018;
|
||||
explut_jt51[8'd001] = 10'd1013;
|
||||
explut_jt51[8'd002] = 10'd1007;
|
||||
explut_jt51[8'd003] = 10'd1002;
|
||||
explut_jt51[8'd004] = 10'd0996;
|
||||
explut_jt51[8'd005] = 10'd0991;
|
||||
explut_jt51[8'd006] = 10'd0986;
|
||||
explut_jt51[8'd007] = 10'd0980;
|
||||
explut_jt51[8'd008] = 10'd0975;
|
||||
explut_jt51[8'd009] = 10'd0969;
|
||||
explut_jt51[8'd010] = 10'd0964;
|
||||
explut_jt51[8'd011] = 10'd0959;
|
||||
explut_jt51[8'd012] = 10'd0953;
|
||||
explut_jt51[8'd013] = 10'd0948;
|
||||
explut_jt51[8'd014] = 10'd0942;
|
||||
explut_jt51[8'd015] = 10'd0937;
|
||||
explut_jt51[8'd016] = 10'd0932;
|
||||
explut_jt51[8'd017] = 10'd0927;
|
||||
explut_jt51[8'd018] = 10'd0921;
|
||||
explut_jt51[8'd019] = 10'd0916;
|
||||
explut_jt51[8'd020] = 10'd0911;
|
||||
explut_jt51[8'd021] = 10'd0906;
|
||||
explut_jt51[8'd022] = 10'd0900;
|
||||
explut_jt51[8'd023] = 10'd0895;
|
||||
explut_jt51[8'd024] = 10'd0890;
|
||||
explut_jt51[8'd025] = 10'd0885;
|
||||
explut_jt51[8'd026] = 10'd0880;
|
||||
explut_jt51[8'd027] = 10'd0874;
|
||||
explut_jt51[8'd028] = 10'd0869;
|
||||
explut_jt51[8'd029] = 10'd0864;
|
||||
explut_jt51[8'd030] = 10'd0859;
|
||||
explut_jt51[8'd031] = 10'd0854;
|
||||
explut_jt51[8'd032] = 10'd0849;
|
||||
explut_jt51[8'd033] = 10'd0844;
|
||||
explut_jt51[8'd034] = 10'd0839;
|
||||
explut_jt51[8'd035] = 10'd0834;
|
||||
explut_jt51[8'd036] = 10'd0829;
|
||||
explut_jt51[8'd037] = 10'd0824;
|
||||
explut_jt51[8'd038] = 10'd0819;
|
||||
explut_jt51[8'd039] = 10'd0814;
|
||||
explut_jt51[8'd040] = 10'd0809;
|
||||
explut_jt51[8'd041] = 10'd0804;
|
||||
explut_jt51[8'd042] = 10'd0799;
|
||||
explut_jt51[8'd043] = 10'd0794;
|
||||
explut_jt51[8'd044] = 10'd0789;
|
||||
explut_jt51[8'd045] = 10'd0784;
|
||||
explut_jt51[8'd046] = 10'd0779;
|
||||
explut_jt51[8'd047] = 10'd0774;
|
||||
explut_jt51[8'd048] = 10'd0770;
|
||||
explut_jt51[8'd049] = 10'd0765;
|
||||
explut_jt51[8'd050] = 10'd0760;
|
||||
explut_jt51[8'd051] = 10'd0755;
|
||||
explut_jt51[8'd052] = 10'd0750;
|
||||
explut_jt51[8'd053] = 10'd0745;
|
||||
explut_jt51[8'd054] = 10'd0741;
|
||||
explut_jt51[8'd055] = 10'd0736;
|
||||
explut_jt51[8'd056] = 10'd0731;
|
||||
explut_jt51[8'd057] = 10'd0726;
|
||||
explut_jt51[8'd058] = 10'd0722;
|
||||
explut_jt51[8'd059] = 10'd0717;
|
||||
explut_jt51[8'd060] = 10'd0712;
|
||||
explut_jt51[8'd061] = 10'd0708;
|
||||
explut_jt51[8'd062] = 10'd0703;
|
||||
explut_jt51[8'd063] = 10'd0698;
|
||||
explut_jt51[8'd064] = 10'd0693;
|
||||
explut_jt51[8'd065] = 10'd0689;
|
||||
explut_jt51[8'd066] = 10'd0684;
|
||||
explut_jt51[8'd067] = 10'd0680;
|
||||
explut_jt51[8'd068] = 10'd0675;
|
||||
explut_jt51[8'd069] = 10'd0670;
|
||||
explut_jt51[8'd070] = 10'd0666;
|
||||
explut_jt51[8'd071] = 10'd0661;
|
||||
explut_jt51[8'd072] = 10'd0657;
|
||||
explut_jt51[8'd073] = 10'd0652;
|
||||
explut_jt51[8'd074] = 10'd0648;
|
||||
explut_jt51[8'd075] = 10'd0643;
|
||||
explut_jt51[8'd076] = 10'd0639;
|
||||
explut_jt51[8'd077] = 10'd0634;
|
||||
explut_jt51[8'd078] = 10'd0630;
|
||||
explut_jt51[8'd079] = 10'd0625;
|
||||
explut_jt51[8'd080] = 10'd0621;
|
||||
explut_jt51[8'd081] = 10'd0616;
|
||||
explut_jt51[8'd082] = 10'd0612;
|
||||
explut_jt51[8'd083] = 10'd0607;
|
||||
explut_jt51[8'd084] = 10'd0603;
|
||||
explut_jt51[8'd085] = 10'd0599;
|
||||
explut_jt51[8'd086] = 10'd0594;
|
||||
explut_jt51[8'd087] = 10'd0590;
|
||||
explut_jt51[8'd088] = 10'd0585;
|
||||
explut_jt51[8'd089] = 10'd0581;
|
||||
explut_jt51[8'd090] = 10'd0577;
|
||||
explut_jt51[8'd091] = 10'd0572;
|
||||
explut_jt51[8'd092] = 10'd0568;
|
||||
explut_jt51[8'd093] = 10'd0564;
|
||||
explut_jt51[8'd094] = 10'd0560;
|
||||
explut_jt51[8'd095] = 10'd0555;
|
||||
explut_jt51[8'd096] = 10'd0551;
|
||||
explut_jt51[8'd097] = 10'd0547;
|
||||
explut_jt51[8'd098] = 10'd0542;
|
||||
explut_jt51[8'd099] = 10'd0538;
|
||||
explut_jt51[8'd100] = 10'd0534;
|
||||
explut_jt51[8'd101] = 10'd0530;
|
||||
explut_jt51[8'd102] = 10'd0526;
|
||||
explut_jt51[8'd103] = 10'd0521;
|
||||
explut_jt51[8'd104] = 10'd0517;
|
||||
explut_jt51[8'd105] = 10'd0513;
|
||||
explut_jt51[8'd106] = 10'd0509;
|
||||
explut_jt51[8'd107] = 10'd0505;
|
||||
explut_jt51[8'd108] = 10'd0501;
|
||||
explut_jt51[8'd109] = 10'd0496;
|
||||
explut_jt51[8'd110] = 10'd0492;
|
||||
explut_jt51[8'd111] = 10'd0488;
|
||||
explut_jt51[8'd112] = 10'd0484;
|
||||
explut_jt51[8'd113] = 10'd0480;
|
||||
explut_jt51[8'd114] = 10'd0476;
|
||||
explut_jt51[8'd115] = 10'd0472;
|
||||
explut_jt51[8'd116] = 10'd0468;
|
||||
explut_jt51[8'd117] = 10'd0464;
|
||||
explut_jt51[8'd118] = 10'd0460;
|
||||
explut_jt51[8'd119] = 10'd0456;
|
||||
explut_jt51[8'd120] = 10'd0452;
|
||||
explut_jt51[8'd121] = 10'd0448;
|
||||
explut_jt51[8'd122] = 10'd0444;
|
||||
explut_jt51[8'd123] = 10'd0440;
|
||||
explut_jt51[8'd124] = 10'd0436;
|
||||
explut_jt51[8'd125] = 10'd0432;
|
||||
explut_jt51[8'd126] = 10'd0428;
|
||||
explut_jt51[8'd127] = 10'd0424;
|
||||
explut_jt51[8'd128] = 10'd0420;
|
||||
explut_jt51[8'd129] = 10'd0416;
|
||||
explut_jt51[8'd130] = 10'd0412;
|
||||
explut_jt51[8'd131] = 10'd0409;
|
||||
explut_jt51[8'd132] = 10'd0405;
|
||||
explut_jt51[8'd133] = 10'd0401;
|
||||
explut_jt51[8'd134] = 10'd0397;
|
||||
explut_jt51[8'd135] = 10'd0393;
|
||||
explut_jt51[8'd136] = 10'd0389;
|
||||
explut_jt51[8'd137] = 10'd0385;
|
||||
explut_jt51[8'd138] = 10'd0382;
|
||||
explut_jt51[8'd139] = 10'd0378;
|
||||
explut_jt51[8'd140] = 10'd0374;
|
||||
explut_jt51[8'd141] = 10'd0370;
|
||||
explut_jt51[8'd142] = 10'd0367;
|
||||
explut_jt51[8'd143] = 10'd0363;
|
||||
explut_jt51[8'd144] = 10'd0359;
|
||||
explut_jt51[8'd145] = 10'd0355;
|
||||
explut_jt51[8'd146] = 10'd0352;
|
||||
explut_jt51[8'd147] = 10'd0348;
|
||||
explut_jt51[8'd148] = 10'd0344;
|
||||
explut_jt51[8'd149] = 10'd0340;
|
||||
explut_jt51[8'd150] = 10'd0337;
|
||||
explut_jt51[8'd151] = 10'd0333;
|
||||
explut_jt51[8'd152] = 10'd0329;
|
||||
explut_jt51[8'd153] = 10'd0326;
|
||||
explut_jt51[8'd154] = 10'd0322;
|
||||
explut_jt51[8'd155] = 10'd0318;
|
||||
explut_jt51[8'd156] = 10'd0315;
|
||||
explut_jt51[8'd157] = 10'd0311;
|
||||
explut_jt51[8'd158] = 10'd0308;
|
||||
explut_jt51[8'd159] = 10'd0304;
|
||||
explut_jt51[8'd160] = 10'd0300;
|
||||
explut_jt51[8'd161] = 10'd0297;
|
||||
explut_jt51[8'd162] = 10'd0293;
|
||||
explut_jt51[8'd163] = 10'd0290;
|
||||
explut_jt51[8'd164] = 10'd0286;
|
||||
explut_jt51[8'd165] = 10'd0283;
|
||||
explut_jt51[8'd166] = 10'd0279;
|
||||
explut_jt51[8'd167] = 10'd0276;
|
||||
explut_jt51[8'd168] = 10'd0272;
|
||||
explut_jt51[8'd169] = 10'd0268;
|
||||
explut_jt51[8'd170] = 10'd0265;
|
||||
explut_jt51[8'd171] = 10'd0262;
|
||||
explut_jt51[8'd172] = 10'd0258;
|
||||
explut_jt51[8'd173] = 10'd0255;
|
||||
explut_jt51[8'd174] = 10'd0251;
|
||||
explut_jt51[8'd175] = 10'd0248;
|
||||
explut_jt51[8'd176] = 10'd0244;
|
||||
explut_jt51[8'd177] = 10'd0241;
|
||||
explut_jt51[8'd178] = 10'd0237;
|
||||
explut_jt51[8'd179] = 10'd0234;
|
||||
explut_jt51[8'd180] = 10'd0231;
|
||||
explut_jt51[8'd181] = 10'd0227;
|
||||
explut_jt51[8'd182] = 10'd0224;
|
||||
explut_jt51[8'd183] = 10'd0220;
|
||||
explut_jt51[8'd184] = 10'd0217;
|
||||
explut_jt51[8'd185] = 10'd0214;
|
||||
explut_jt51[8'd186] = 10'd0210;
|
||||
explut_jt51[8'd187] = 10'd0207;
|
||||
explut_jt51[8'd188] = 10'd0204;
|
||||
explut_jt51[8'd189] = 10'd0200;
|
||||
explut_jt51[8'd190] = 10'd0197;
|
||||
explut_jt51[8'd191] = 10'd0194;
|
||||
explut_jt51[8'd192] = 10'd0190;
|
||||
explut_jt51[8'd193] = 10'd0187;
|
||||
explut_jt51[8'd194] = 10'd0184;
|
||||
explut_jt51[8'd195] = 10'd0181;
|
||||
explut_jt51[8'd196] = 10'd0177;
|
||||
explut_jt51[8'd197] = 10'd0174;
|
||||
explut_jt51[8'd198] = 10'd0171;
|
||||
explut_jt51[8'd199] = 10'd0168;
|
||||
explut_jt51[8'd200] = 10'd0164;
|
||||
explut_jt51[8'd201] = 10'd0161;
|
||||
explut_jt51[8'd202] = 10'd0158;
|
||||
explut_jt51[8'd203] = 10'd0155;
|
||||
explut_jt51[8'd204] = 10'd0152;
|
||||
explut_jt51[8'd205] = 10'd0148;
|
||||
explut_jt51[8'd206] = 10'd0145;
|
||||
explut_jt51[8'd207] = 10'd0142;
|
||||
explut_jt51[8'd208] = 10'd0139;
|
||||
explut_jt51[8'd209] = 10'd0136;
|
||||
explut_jt51[8'd210] = 10'd0133;
|
||||
explut_jt51[8'd211] = 10'd0130;
|
||||
explut_jt51[8'd212] = 10'd0126;
|
||||
explut_jt51[8'd213] = 10'd0123;
|
||||
explut_jt51[8'd214] = 10'd0120;
|
||||
explut_jt51[8'd215] = 10'd0117;
|
||||
explut_jt51[8'd216] = 10'd0114;
|
||||
explut_jt51[8'd217] = 10'd0111;
|
||||
explut_jt51[8'd218] = 10'd0108;
|
||||
explut_jt51[8'd219] = 10'd0105;
|
||||
explut_jt51[8'd220] = 10'd0102;
|
||||
explut_jt51[8'd221] = 10'd0099;
|
||||
explut_jt51[8'd222] = 10'd0096;
|
||||
explut_jt51[8'd223] = 10'd0093;
|
||||
explut_jt51[8'd224] = 10'd0090;
|
||||
explut_jt51[8'd225] = 10'd0087;
|
||||
explut_jt51[8'd226] = 10'd0084;
|
||||
explut_jt51[8'd227] = 10'd0081;
|
||||
explut_jt51[8'd228] = 10'd0078;
|
||||
explut_jt51[8'd229] = 10'd0075;
|
||||
explut_jt51[8'd230] = 10'd0072;
|
||||
explut_jt51[8'd231] = 10'd0069;
|
||||
explut_jt51[8'd232] = 10'd0066;
|
||||
explut_jt51[8'd233] = 10'd0063;
|
||||
explut_jt51[8'd234] = 10'd0060;
|
||||
explut_jt51[8'd235] = 10'd0057;
|
||||
explut_jt51[8'd236] = 10'd0054;
|
||||
explut_jt51[8'd237] = 10'd0051;
|
||||
explut_jt51[8'd238] = 10'd0048;
|
||||
explut_jt51[8'd239] = 10'd0045;
|
||||
explut_jt51[8'd240] = 10'd0042;
|
||||
explut_jt51[8'd241] = 10'd0040;
|
||||
explut_jt51[8'd242] = 10'd0037;
|
||||
explut_jt51[8'd243] = 10'd0034;
|
||||
explut_jt51[8'd244] = 10'd0031;
|
||||
explut_jt51[8'd245] = 10'd0028;
|
||||
explut_jt51[8'd246] = 10'd0025;
|
||||
explut_jt51[8'd247] = 10'd0022;
|
||||
explut_jt51[8'd248] = 10'd0020;
|
||||
explut_jt51[8'd249] = 10'd0017;
|
||||
explut_jt51[8'd250] = 10'd0014;
|
||||
explut_jt51[8'd251] = 10'd0011;
|
||||
explut_jt51[8'd252] = 10'd0008;
|
||||
explut_jt51[8'd253] = 10'd0006;
|
||||
explut_jt51[8'd254] = 10'd0003;
|
||||
explut_jt51[8'd255] = 10'd0000;
|
||||
end
|
||||
|
||||
always @ (posedge clk) if(cen)
|
||||
exp <= explut_jt51[addr];
|
||||
|
||||
endmodule
|
||||
80
common/Sound/ym3526/jtopl_lfo.v
Normal file
80
common/Sound/ym3526/jtopl_lfo.v
Normal file
@ -0,0 +1,80 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 21-6-2020
|
||||
*/
|
||||
|
||||
// Follows OPLL Reverse Engineering from Nuked
|
||||
// https://github.com/nukeykt/Nuked-OPLL
|
||||
|
||||
// The AM logic renders a triangular waveform. The logic for it is rather
|
||||
// obscure, but apparently that's how the original was done
|
||||
|
||||
module jtopl_lfo(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cenop,
|
||||
input wire [17:0] slot,
|
||||
output wire [ 2:0] vib_cnt,
|
||||
output reg [ 3:0] trem
|
||||
);
|
||||
|
||||
parameter [6:0] LIM=7'd60;
|
||||
|
||||
reg [12:0] cnt;
|
||||
reg am_inc, am_incen, am_dir, am_step;
|
||||
reg [ 1:0] am_bit;
|
||||
reg am_carry;
|
||||
reg [ 8:0] am_cnt;
|
||||
|
||||
wire [12:0] next = cnt+1'b1;
|
||||
|
||||
assign vib_cnt = cnt[12:10];
|
||||
|
||||
always @(*) begin
|
||||
am_inc = (slot[0] | am_dir ) & am_step & am_incen;
|
||||
am_bit = {1'b0, am_cnt[0]} + {1'b0, am_inc} + {1'b0, am_carry & am_incen};
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if( rst ) begin
|
||||
cnt <= 13'd0;
|
||||
am_incen <= 1;
|
||||
am_dir <= 0;
|
||||
am_carry <= 0;
|
||||
am_cnt <= 9'd0;
|
||||
am_step <= 0;
|
||||
end else if( cenop ) begin
|
||||
if( slot[17] ) begin
|
||||
cnt <= next;
|
||||
am_step <= &next[5:0];
|
||||
am_incen <= 1;
|
||||
end
|
||||
else if(slot[8]) am_incen <= 0;
|
||||
am_cnt <= { am_bit[0], am_cnt[8:1] };
|
||||
am_carry <= am_bit[1];
|
||||
if( slot[0] ) begin
|
||||
if( am_dir && am_cnt[6:0]==7'd0 ) am_dir <= 0;
|
||||
else
|
||||
if( !am_dir && ( (am_cnt[6:0]&7'h69) == 7'h69) ) am_dir <= 1;
|
||||
end
|
||||
// output
|
||||
if( slot[0] ) trem <= am_cnt[6:3];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
297
common/Sound/ym3526/jtopl_logsin.v
Normal file
297
common/Sound/ym3526/jtopl_logsin.v
Normal file
@ -0,0 +1,297 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
|
||||
*/
|
||||
|
||||
//altera message_off 10030
|
||||
|
||||
module jtopl_logsin(
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
input wire [ 7:0] addr,
|
||||
output reg [11:0] logsin
|
||||
);
|
||||
|
||||
reg [11:0] sinelut[255:0];
|
||||
initial begin
|
||||
sinelut[8'd000] = 12'h000;
|
||||
sinelut[8'd001] = 12'h000;
|
||||
sinelut[8'd002] = 12'h000;
|
||||
sinelut[8'd003] = 12'h000;
|
||||
sinelut[8'd004] = 12'h000;
|
||||
sinelut[8'd005] = 12'h000;
|
||||
sinelut[8'd006] = 12'h000;
|
||||
sinelut[8'd007] = 12'h000;
|
||||
sinelut[8'd008] = 12'h001;
|
||||
sinelut[8'd009] = 12'h001;
|
||||
sinelut[8'd010] = 12'h001;
|
||||
sinelut[8'd011] = 12'h001;
|
||||
sinelut[8'd012] = 12'h001;
|
||||
sinelut[8'd013] = 12'h001;
|
||||
sinelut[8'd014] = 12'h001;
|
||||
sinelut[8'd015] = 12'h002;
|
||||
sinelut[8'd016] = 12'h002;
|
||||
sinelut[8'd017] = 12'h002;
|
||||
sinelut[8'd018] = 12'h002;
|
||||
sinelut[8'd019] = 12'h003;
|
||||
sinelut[8'd020] = 12'h003;
|
||||
sinelut[8'd021] = 12'h003;
|
||||
sinelut[8'd022] = 12'h004;
|
||||
sinelut[8'd023] = 12'h004;
|
||||
sinelut[8'd024] = 12'h004;
|
||||
sinelut[8'd025] = 12'h005;
|
||||
sinelut[8'd026] = 12'h005;
|
||||
sinelut[8'd027] = 12'h005;
|
||||
sinelut[8'd028] = 12'h006;
|
||||
sinelut[8'd029] = 12'h006;
|
||||
sinelut[8'd030] = 12'h007;
|
||||
sinelut[8'd031] = 12'h007;
|
||||
sinelut[8'd032] = 12'h007;
|
||||
sinelut[8'd033] = 12'h008;
|
||||
sinelut[8'd034] = 12'h008;
|
||||
sinelut[8'd035] = 12'h009;
|
||||
sinelut[8'd036] = 12'h009;
|
||||
sinelut[8'd037] = 12'h00a;
|
||||
sinelut[8'd038] = 12'h00a;
|
||||
sinelut[8'd039] = 12'h00b;
|
||||
sinelut[8'd040] = 12'h00c;
|
||||
sinelut[8'd041] = 12'h00c;
|
||||
sinelut[8'd042] = 12'h00d;
|
||||
sinelut[8'd043] = 12'h00d;
|
||||
sinelut[8'd044] = 12'h00e;
|
||||
sinelut[8'd045] = 12'h00f;
|
||||
sinelut[8'd046] = 12'h00f;
|
||||
sinelut[8'd047] = 12'h010;
|
||||
sinelut[8'd048] = 12'h011;
|
||||
sinelut[8'd049] = 12'h011;
|
||||
sinelut[8'd050] = 12'h012;
|
||||
sinelut[8'd051] = 12'h013;
|
||||
sinelut[8'd052] = 12'h014;
|
||||
sinelut[8'd053] = 12'h014;
|
||||
sinelut[8'd054] = 12'h015;
|
||||
sinelut[8'd055] = 12'h016;
|
||||
sinelut[8'd056] = 12'h017;
|
||||
sinelut[8'd057] = 12'h017;
|
||||
sinelut[8'd058] = 12'h018;
|
||||
sinelut[8'd059] = 12'h019;
|
||||
sinelut[8'd060] = 12'h01a;
|
||||
sinelut[8'd061] = 12'h01b;
|
||||
sinelut[8'd062] = 12'h01c;
|
||||
sinelut[8'd063] = 12'h01d;
|
||||
sinelut[8'd064] = 12'h01e;
|
||||
sinelut[8'd065] = 12'h01f;
|
||||
sinelut[8'd066] = 12'h020;
|
||||
sinelut[8'd067] = 12'h021;
|
||||
sinelut[8'd068] = 12'h022;
|
||||
sinelut[8'd069] = 12'h023;
|
||||
sinelut[8'd070] = 12'h024;
|
||||
sinelut[8'd071] = 12'h025;
|
||||
sinelut[8'd072] = 12'h026;
|
||||
sinelut[8'd073] = 12'h027;
|
||||
sinelut[8'd074] = 12'h028;
|
||||
sinelut[8'd075] = 12'h029;
|
||||
sinelut[8'd076] = 12'h02a;
|
||||
sinelut[8'd077] = 12'h02b;
|
||||
sinelut[8'd078] = 12'h02d;
|
||||
sinelut[8'd079] = 12'h02e;
|
||||
sinelut[8'd080] = 12'h02f;
|
||||
sinelut[8'd081] = 12'h030;
|
||||
sinelut[8'd082] = 12'h031;
|
||||
sinelut[8'd083] = 12'h033;
|
||||
sinelut[8'd084] = 12'h034;
|
||||
sinelut[8'd085] = 12'h035;
|
||||
sinelut[8'd086] = 12'h037;
|
||||
sinelut[8'd087] = 12'h038;
|
||||
sinelut[8'd088] = 12'h039;
|
||||
sinelut[8'd089] = 12'h03b;
|
||||
sinelut[8'd090] = 12'h03c;
|
||||
sinelut[8'd091] = 12'h03e;
|
||||
sinelut[8'd092] = 12'h03f;
|
||||
sinelut[8'd093] = 12'h040;
|
||||
sinelut[8'd094] = 12'h042;
|
||||
sinelut[8'd095] = 12'h043;
|
||||
sinelut[8'd096] = 12'h045;
|
||||
sinelut[8'd097] = 12'h046;
|
||||
sinelut[8'd098] = 12'h048;
|
||||
sinelut[8'd099] = 12'h04a;
|
||||
sinelut[8'd100] = 12'h04b;
|
||||
sinelut[8'd101] = 12'h04d;
|
||||
sinelut[8'd102] = 12'h04e;
|
||||
sinelut[8'd103] = 12'h050;
|
||||
sinelut[8'd104] = 12'h052;
|
||||
sinelut[8'd105] = 12'h053;
|
||||
sinelut[8'd106] = 12'h055;
|
||||
sinelut[8'd107] = 12'h057;
|
||||
sinelut[8'd108] = 12'h059;
|
||||
sinelut[8'd109] = 12'h05b;
|
||||
sinelut[8'd110] = 12'h05c;
|
||||
sinelut[8'd111] = 12'h05e;
|
||||
sinelut[8'd112] = 12'h060;
|
||||
sinelut[8'd113] = 12'h062;
|
||||
sinelut[8'd114] = 12'h064;
|
||||
sinelut[8'd115] = 12'h066;
|
||||
sinelut[8'd116] = 12'h068;
|
||||
sinelut[8'd117] = 12'h06a;
|
||||
sinelut[8'd118] = 12'h06c;
|
||||
sinelut[8'd119] = 12'h06e;
|
||||
sinelut[8'd120] = 12'h070;
|
||||
sinelut[8'd121] = 12'h072;
|
||||
sinelut[8'd122] = 12'h074;
|
||||
sinelut[8'd123] = 12'h076;
|
||||
sinelut[8'd124] = 12'h078;
|
||||
sinelut[8'd125] = 12'h07a;
|
||||
sinelut[8'd126] = 12'h07d;
|
||||
sinelut[8'd127] = 12'h07f;
|
||||
sinelut[8'd128] = 12'h081;
|
||||
sinelut[8'd129] = 12'h083;
|
||||
sinelut[8'd130] = 12'h086;
|
||||
sinelut[8'd131] = 12'h088;
|
||||
sinelut[8'd132] = 12'h08a;
|
||||
sinelut[8'd133] = 12'h08d;
|
||||
sinelut[8'd134] = 12'h08f;
|
||||
sinelut[8'd135] = 12'h092;
|
||||
sinelut[8'd136] = 12'h094;
|
||||
sinelut[8'd137] = 12'h097;
|
||||
sinelut[8'd138] = 12'h099;
|
||||
sinelut[8'd139] = 12'h09c;
|
||||
sinelut[8'd140] = 12'h09f;
|
||||
sinelut[8'd141] = 12'h0a1;
|
||||
sinelut[8'd142] = 12'h0a4;
|
||||
sinelut[8'd143] = 12'h0a7;
|
||||
sinelut[8'd144] = 12'h0a9;
|
||||
sinelut[8'd145] = 12'h0ac;
|
||||
sinelut[8'd146] = 12'h0af;
|
||||
sinelut[8'd147] = 12'h0b2;
|
||||
sinelut[8'd148] = 12'h0b5;
|
||||
sinelut[8'd149] = 12'h0b8;
|
||||
sinelut[8'd150] = 12'h0bb;
|
||||
sinelut[8'd151] = 12'h0be;
|
||||
sinelut[8'd152] = 12'h0c1;
|
||||
sinelut[8'd153] = 12'h0c4;
|
||||
sinelut[8'd154] = 12'h0c7;
|
||||
sinelut[8'd155] = 12'h0ca;
|
||||
sinelut[8'd156] = 12'h0cd;
|
||||
sinelut[8'd157] = 12'h0d1;
|
||||
sinelut[8'd158] = 12'h0d4;
|
||||
sinelut[8'd159] = 12'h0d7;
|
||||
sinelut[8'd160] = 12'h0db;
|
||||
sinelut[8'd161] = 12'h0de;
|
||||
sinelut[8'd162] = 12'h0e2;
|
||||
sinelut[8'd163] = 12'h0e5;
|
||||
sinelut[8'd164] = 12'h0e9;
|
||||
sinelut[8'd165] = 12'h0ec;
|
||||
sinelut[8'd166] = 12'h0f0;
|
||||
sinelut[8'd167] = 12'h0f4;
|
||||
sinelut[8'd168] = 12'h0f8;
|
||||
sinelut[8'd169] = 12'h0fb;
|
||||
sinelut[8'd170] = 12'h0ff;
|
||||
sinelut[8'd171] = 12'h103;
|
||||
sinelut[8'd172] = 12'h107;
|
||||
sinelut[8'd173] = 12'h10b;
|
||||
sinelut[8'd174] = 12'h10f;
|
||||
sinelut[8'd175] = 12'h114;
|
||||
sinelut[8'd176] = 12'h118;
|
||||
sinelut[8'd177] = 12'h11c;
|
||||
sinelut[8'd178] = 12'h121;
|
||||
sinelut[8'd179] = 12'h125;
|
||||
sinelut[8'd180] = 12'h129;
|
||||
sinelut[8'd181] = 12'h12e;
|
||||
sinelut[8'd182] = 12'h133;
|
||||
sinelut[8'd183] = 12'h137;
|
||||
sinelut[8'd184] = 12'h13c;
|
||||
sinelut[8'd185] = 12'h141;
|
||||
sinelut[8'd186] = 12'h146;
|
||||
sinelut[8'd187] = 12'h14b;
|
||||
sinelut[8'd188] = 12'h150;
|
||||
sinelut[8'd189] = 12'h155;
|
||||
sinelut[8'd190] = 12'h15b;
|
||||
sinelut[8'd191] = 12'h160;
|
||||
sinelut[8'd192] = 12'h166;
|
||||
sinelut[8'd193] = 12'h16b;
|
||||
sinelut[8'd194] = 12'h171;
|
||||
sinelut[8'd195] = 12'h177;
|
||||
sinelut[8'd196] = 12'h17c;
|
||||
sinelut[8'd197] = 12'h182;
|
||||
sinelut[8'd198] = 12'h188;
|
||||
sinelut[8'd199] = 12'h18f;
|
||||
sinelut[8'd200] = 12'h195;
|
||||
sinelut[8'd201] = 12'h19b;
|
||||
sinelut[8'd202] = 12'h1a2;
|
||||
sinelut[8'd203] = 12'h1a9;
|
||||
sinelut[8'd204] = 12'h1b0;
|
||||
sinelut[8'd205] = 12'h1b7;
|
||||
sinelut[8'd206] = 12'h1be;
|
||||
sinelut[8'd207] = 12'h1c5;
|
||||
sinelut[8'd208] = 12'h1cd;
|
||||
sinelut[8'd209] = 12'h1d4;
|
||||
sinelut[8'd210] = 12'h1dc;
|
||||
sinelut[8'd211] = 12'h1e4;
|
||||
sinelut[8'd212] = 12'h1ec;
|
||||
sinelut[8'd213] = 12'h1f5;
|
||||
sinelut[8'd214] = 12'h1fd;
|
||||
sinelut[8'd215] = 12'h206;
|
||||
sinelut[8'd216] = 12'h20f;
|
||||
sinelut[8'd217] = 12'h218;
|
||||
sinelut[8'd218] = 12'h222;
|
||||
sinelut[8'd219] = 12'h22c;
|
||||
sinelut[8'd220] = 12'h236;
|
||||
sinelut[8'd221] = 12'h240;
|
||||
sinelut[8'd222] = 12'h24b;
|
||||
sinelut[8'd223] = 12'h256;
|
||||
sinelut[8'd224] = 12'h261;
|
||||
sinelut[8'd225] = 12'h26d;
|
||||
sinelut[8'd226] = 12'h279;
|
||||
sinelut[8'd227] = 12'h286;
|
||||
sinelut[8'd228] = 12'h293;
|
||||
sinelut[8'd229] = 12'h2a0;
|
||||
sinelut[8'd230] = 12'h2af;
|
||||
sinelut[8'd231] = 12'h2bd;
|
||||
sinelut[8'd232] = 12'h2cd;
|
||||
sinelut[8'd233] = 12'h2dc;
|
||||
sinelut[8'd234] = 12'h2ed;
|
||||
sinelut[8'd235] = 12'h2ff;
|
||||
sinelut[8'd236] = 12'h311;
|
||||
sinelut[8'd237] = 12'h324;
|
||||
sinelut[8'd238] = 12'h339;
|
||||
sinelut[8'd239] = 12'h34e;
|
||||
sinelut[8'd240] = 12'h365;
|
||||
sinelut[8'd241] = 12'h37e;
|
||||
sinelut[8'd242] = 12'h398;
|
||||
sinelut[8'd243] = 12'h3b5;
|
||||
sinelut[8'd244] = 12'h3d3;
|
||||
sinelut[8'd245] = 12'h3f5;
|
||||
sinelut[8'd246] = 12'h41a;
|
||||
sinelut[8'd247] = 12'h443;
|
||||
sinelut[8'd248] = 12'h471;
|
||||
sinelut[8'd249] = 12'h4a6;
|
||||
sinelut[8'd250] = 12'h4e4;
|
||||
sinelut[8'd251] = 12'h52e;
|
||||
sinelut[8'd252] = 12'h58b;
|
||||
sinelut[8'd253] = 12'h607;
|
||||
sinelut[8'd254] = 12'h6c3;
|
||||
sinelut[8'd255] = 12'h859;
|
||||
end
|
||||
|
||||
always @ (posedge clk) if(cen) begin
|
||||
logsin <= sinelut[addr];
|
||||
end
|
||||
|
||||
endmodule
|
||||
277
common/Sound/ym3526/jtopl_mmr.v
Normal file
277
common/Sound/ym3526/jtopl_mmr.v
Normal file
@ -0,0 +1,277 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 10-6-2020
|
||||
*/
|
||||
|
||||
module jtopl_mmr #(parameter OPL_TYPE=1)
|
||||
(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
output wire cenop,
|
||||
input wire [ 7:0] din,
|
||||
input wire write,
|
||||
input wire addr,
|
||||
// location
|
||||
output wire zero,
|
||||
output wire [ 1:0] group,
|
||||
output wire op,
|
||||
output wire [17:0] slot,
|
||||
output reg rhy_en,
|
||||
// Timers
|
||||
output reg [ 7:0] value_A,
|
||||
output reg [ 7:0] value_B,
|
||||
output reg load_A,
|
||||
output reg load_B,
|
||||
output reg flagen_A,
|
||||
output reg flagen_B,
|
||||
output reg clr_flag_A,
|
||||
output reg clr_flag_B,
|
||||
input wire flag_A,
|
||||
input wire overflow_A,
|
||||
// Phase Generator
|
||||
output wire [ 9:0] fnum_I,
|
||||
output wire [ 2:0] block_I,
|
||||
output wire [ 3:0] mul_II,
|
||||
output wire viben_I,
|
||||
// Operator
|
||||
output wire [ 1:0] wavsel_I,
|
||||
// Envelope Generator
|
||||
output wire keyon_I,
|
||||
output wire en_sus_I, // enable sustain
|
||||
output wire [ 3:0] arate_I, // attack rate
|
||||
output wire [ 3:0] drate_I, // decay rate
|
||||
output wire [ 3:0] rrate_I, // release rate
|
||||
output wire [ 3:0] sl_I, // sustain level
|
||||
output wire ks_II, // key scale
|
||||
output wire [ 5:0] tl_IV,
|
||||
output wire amen_IV,
|
||||
// global values
|
||||
output reg am_dep,
|
||||
output reg vib_dep,
|
||||
output wire [ 1:0] ksl_IV,
|
||||
// Operator configuration
|
||||
output wire [ 2:0] fb_I,
|
||||
output wire con_I
|
||||
);
|
||||
|
||||
//parameter OPL_TYPE=1;
|
||||
|
||||
jtopl_div #(OPL_TYPE) u_div (
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.cenop ( cenop )
|
||||
);
|
||||
|
||||
localparam [7:0] REG_TESTYM = 8'h01,
|
||||
REG_CLKA = 8'h02,
|
||||
REG_CLKB = 8'h03,
|
||||
REG_TIMER = 8'h04,
|
||||
REG_CSM = 8'h08,
|
||||
REG_RYTHM = 8'hBD;
|
||||
|
||||
reg [ 7:0] selreg; // selected register
|
||||
reg [ 7:0] din_copy;
|
||||
reg csm, effect;
|
||||
reg [ 1:0] sel_group; // group to update
|
||||
reg [ 2:0] sel_sub; // subslot to update
|
||||
reg up_fnumlo, up_fnumhi, up_fbcon,
|
||||
up_mult, up_ksl_tl, up_ar_dr, up_sl_rr,
|
||||
up_wav;
|
||||
reg wave_mode, // 1 if waveform selection is enabled (OPL2)
|
||||
csm_en,
|
||||
note_sel; // keyboard split, not implemented
|
||||
reg [ 4:0] rhy_kon;
|
||||
|
||||
// this runs at clk speed, no clock gating here
|
||||
// if I try to make this an async rst it fails to map it
|
||||
// as flip flops but uses latches instead. So I keep it as sync. reset
|
||||
always @(posedge clk) begin
|
||||
if( rst ) begin
|
||||
selreg <= 8'h0;
|
||||
sel_group <= 2'd0;
|
||||
sel_sub <= 3'd0;
|
||||
// Updaters
|
||||
up_fbcon <= 0;
|
||||
up_fnumlo <= 0;
|
||||
up_fnumhi <= 0;
|
||||
up_mult <= 0;
|
||||
up_ksl_tl <= 0;
|
||||
up_ar_dr <= 0;
|
||||
up_sl_rr <= 0;
|
||||
up_wav <= 0;
|
||||
// Rhythms
|
||||
rhy_en <= 0;
|
||||
rhy_kon <= 5'd0;
|
||||
// sensitivity to LFO
|
||||
am_dep <= 0;
|
||||
vib_dep <= 0;
|
||||
csm_en <= 0;
|
||||
note_sel <= 0;
|
||||
// OPL2 waveforms
|
||||
wave_mode <= 0;
|
||||
// timers
|
||||
{ value_A, value_B } <= 16'd0;
|
||||
{ clr_flag_B, clr_flag_A, load_B, load_A } <= 4'd0;
|
||||
flagen_A <= 1;
|
||||
flagen_B <= 1;
|
||||
din_copy <= 8'd0;
|
||||
end else begin
|
||||
// WRITE IN REGISTERS
|
||||
if( write ) begin
|
||||
if( !addr ) begin
|
||||
$display ("[[[ YM3526 ]]] READ_VALUE:%02h t=%0t", din , $realtime);
|
||||
selreg <= din;
|
||||
end else begin
|
||||
// Global registers
|
||||
din_copy <= din;
|
||||
up_fnumhi <= 0;
|
||||
up_fnumlo <= 0;
|
||||
up_fbcon <= 0;
|
||||
up_mult <= 0;
|
||||
up_ksl_tl <= 0;
|
||||
up_ar_dr <= 0;
|
||||
up_sl_rr <= 0;
|
||||
up_wav <= 0;
|
||||
// General control (<0x20 registers)
|
||||
casez( selreg )
|
||||
REG_TESTYM: if(OPL_TYPE>1) wave_mode <= din[5];
|
||||
REG_CLKA: begin value_A <= din; $display ("[[[ YM3526 ]]] REG_CLKA t=%0t" , $realtime); end
|
||||
REG_CLKB: begin value_B <= din; $display ("[[[ YM3526 ]]] REG_CLKB t=%0t" , $realtime); end
|
||||
REG_TIMER: begin
|
||||
$display ("[[[ YM3526 ]]] REG_TIMER t=%0t" , $realtime);
|
||||
clr_flag_A <= din[7];
|
||||
clr_flag_B <= din[7];
|
||||
if (~din[7]) begin
|
||||
flagen_A <= ~din[6];
|
||||
flagen_B <= ~din[5];
|
||||
{ load_B, load_A } <= din[1:0];
|
||||
end
|
||||
end
|
||||
REG_CSM: begin {csm_en, note_sel} <= din[7:6]; $display ("[[[ YM3526 ]]] REG_CSM t=%0t" , $realtime); end
|
||||
default:;
|
||||
endcase
|
||||
// Operator registers
|
||||
if( selreg >= 8'h20 &&
|
||||
(selreg < 8'hA0 || (selreg>=8'hE0 && OPL_TYPE>1) ) &&
|
||||
selreg[2:0]<=3'd5 && selreg[4:3]!=2'b11) begin
|
||||
sel_group <= selreg[4:3];
|
||||
sel_sub <= selreg[2:0];
|
||||
$display ("[[[ YM3526 ]]] OPERATOR REGISTERS t=%0t" , $realtime);
|
||||
case( selreg[7:5] )
|
||||
3'b001: up_mult <= 1;
|
||||
3'b010: up_ksl_tl <= 1;
|
||||
3'b011: up_ar_dr <= 1;
|
||||
3'b100: up_sl_rr <= 1;
|
||||
3'b111: up_wav <= OPL_TYPE!=1;
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
// Channel registers
|
||||
if( selreg[3:0]<=4'd8) begin
|
||||
$display ("[[[ YM3526 ]]] CHANNEL REGISTERS t=%0t", $realtime);
|
||||
case( selreg[7:4] )
|
||||
4'hA: up_fnumlo <= 1;
|
||||
4'hB: up_fnumhi <= 1;
|
||||
4'hC: up_fbcon <= 1;
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
if( selreg[7:4]>=4'hA && selreg[7:4]<4'hd
|
||||
&& selreg[3:0]<=8 ) begin
|
||||
$display ("[[[ YM3526 ]]] SEL_GROUP,SUB REGISTERS t=%0t", $realtime);
|
||||
sel_group <= selreg[3:0] < 4'd3 ? 2'd0 :
|
||||
( selreg[3:0] < 4'd6 ? 2'd1 :
|
||||
( selreg[3:0] < 4'd9 ? 2'd2 : 2'd3) );
|
||||
sel_sub <= selreg[3:0] < 4'd6 ? selreg[2:0] :
|
||||
{ 1'b0, ~&selreg[2:1], selreg[0] };
|
||||
end
|
||||
// Global register
|
||||
if( selreg==REG_RYTHM ) begin
|
||||
$display ("[[[ YM3526 ]]] REG_RYTHM t=%0t" , $realtime);
|
||||
am_dep <= din[7];
|
||||
vib_dep <= din[6];
|
||||
rhy_en <= din[5];
|
||||
rhy_kon <= din[4:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
else if(cenop) begin /* clear once-only bits */
|
||||
{ clr_flag_B, clr_flag_A } <= 2'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
jtopl_reg #(.OPL_TYPE(OPL_TYPE)) u_reg(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( din_copy ),
|
||||
.write ( write ),
|
||||
// Pipeline order
|
||||
.zero ( zero ),
|
||||
.group ( group ),
|
||||
.op ( op ),
|
||||
.slot ( slot ),
|
||||
|
||||
.sel_group ( sel_group ), // group to update
|
||||
.sel_sub ( sel_sub ), // subslot to update
|
||||
|
||||
.rhy_en ( rhy_en ),
|
||||
.rhy_kon ( rhy_kon ),
|
||||
|
||||
//input csm,
|
||||
//input flag_A,
|
||||
//input overflow_A,
|
||||
|
||||
.up_fbcon ( up_fbcon ),
|
||||
.up_fnumlo ( up_fnumlo ),
|
||||
.up_fnumhi ( up_fnumhi ),
|
||||
|
||||
.up_mult ( up_mult ),
|
||||
.up_ksl_tl ( up_ksl_tl ),
|
||||
.up_ar_dr ( up_ar_dr ),
|
||||
.up_sl_rr ( up_sl_rr ),
|
||||
.up_wav ( up_wav ),
|
||||
|
||||
// PG
|
||||
.fnum_I ( fnum_I ),
|
||||
.block_I ( block_I ),
|
||||
.mul_II ( mul_II ),
|
||||
.viben_I ( viben_I ),
|
||||
// OP
|
||||
.wavsel_I ( wavsel_I ),
|
||||
.wave_mode ( wave_mode ),
|
||||
// EG
|
||||
.keyon_I ( keyon_I ),
|
||||
.en_sus_I ( en_sus_I ),
|
||||
.arate_I ( arate_I ),
|
||||
.drate_I ( drate_I ),
|
||||
.rrate_I ( rrate_I ),
|
||||
.sl_I ( sl_I ),
|
||||
.ks_II ( ks_II ),
|
||||
.ksl_IV ( ksl_IV ),
|
||||
.amen_IV ( amen_IV ),
|
||||
.tl_IV ( tl_IV ),
|
||||
// Timbre - Neiro
|
||||
.fb_I ( fb_I ),
|
||||
.con_I ( con_I )
|
||||
);
|
||||
|
||||
endmodule
|
||||
47
common/Sound/ym3526/jtopl_noise.v
Normal file
47
common/Sound/ym3526/jtopl_noise.v
Normal file
@ -0,0 +1,47 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 24-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_noise(
|
||||
input wire rst, // rst should be at least 6 clk&cen cycles long
|
||||
input wire clk, // CPU clock
|
||||
input wire cen, // optional clock enable, it not needed leave as 1'b1
|
||||
output wire noise
|
||||
);
|
||||
|
||||
reg [22:0] no;
|
||||
reg nbit;
|
||||
|
||||
assign noise = no[0];
|
||||
|
||||
always @(*) begin
|
||||
nbit = no[0] ^ no[14];
|
||||
nbit = nbit | (no==23'd0);
|
||||
end
|
||||
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst )
|
||||
no <= 23'd1<<22;
|
||||
else if(cen) begin
|
||||
no <= { nbit, no[22:1] };
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
263
common/Sound/ym3526/jtopl_op.v
Normal file
263
common/Sound/ym3526/jtopl_op.v
Normal file
@ -0,0 +1,263 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Based on Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 19-6-2020
|
||||
|
||||
*/
|
||||
|
||||
|
||||
module jtopl_op #(parameter OPL_TYPE=1)
|
||||
(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cenop,
|
||||
|
||||
// these signals need be delayed
|
||||
input wire [1:0] group,
|
||||
input wire op, // 0 for modulator operators
|
||||
input wire con_I,
|
||||
input wire [2:0] fb_I, // voice feedback
|
||||
|
||||
input wire zero,
|
||||
|
||||
input wire [9:0] pg_phase_I,
|
||||
input wire [1:0] wavsel_I,
|
||||
input wire [9:0] eg_atten_II, // output from envelope generator
|
||||
|
||||
|
||||
output reg signed [12:0] op_result,
|
||||
output wire op_out,
|
||||
output wire con_out
|
||||
);
|
||||
|
||||
//parameter OPL_TYPE=1;
|
||||
|
||||
localparam OPW=13, // Operator Width
|
||||
PW=OPW*2; // Previous data Width
|
||||
|
||||
reg [11:0] level_II;
|
||||
reg signbit_II, signbit_III;
|
||||
reg nullify_II;
|
||||
|
||||
wire [ 8:0] ctrl_in, ctrl_dly;
|
||||
wire [ 1:0] group_d;
|
||||
wire op_d, con_I_d;
|
||||
wire [ 1:0] wavsel_d;
|
||||
wire [ 2:0] fb_I_d;
|
||||
|
||||
reg [PW-1:0] prev, prev0_din, prev1_din, prev2_din;
|
||||
wire [PW-1:0] prev0, prev1, prev2;
|
||||
|
||||
assign ctrl_in = { wavsel_I, group, op, con_I, fb_I };
|
||||
assign { wavsel_d, group_d, op_d, con_I_d, fb_I_d } = ctrl_dly;
|
||||
|
||||
jtopl_sh #( .width(9), .stages(3)) u_delay(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( ctrl_in ),
|
||||
.drop ( ctrl_dly )
|
||||
);
|
||||
|
||||
jtopl_sh #( .width(2), .stages(3)) u_condly(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( {op_d, con_I_d} ),
|
||||
.drop ( {op_out, con_out} )
|
||||
);
|
||||
|
||||
always @(*) begin
|
||||
prev0_din = op_d && group_d==2'd0 ? { prev0[OPW-1:0], op_result } : prev0;
|
||||
prev1_din = op_d && group_d==2'd1 ? { prev1[OPW-1:0], op_result } : prev1;
|
||||
prev2_din = op_d && group_d==2'd2 ? { prev2[OPW-1:0], op_result } : prev2;
|
||||
case( group_d )
|
||||
default: prev = prev0;
|
||||
2'd1: prev = prev1;
|
||||
2'd2: prev = prev2;
|
||||
endcase
|
||||
end
|
||||
|
||||
jtopl_sh #( .width(PW), .stages(3)) u_csr0(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( prev0_din ),
|
||||
.drop ( prev0 )
|
||||
);
|
||||
|
||||
jtopl_sh #( .width(PW), .stages(3)) u_csr1(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( prev1_din ),
|
||||
.drop ( prev1 )
|
||||
);
|
||||
|
||||
jtopl_sh #( .width(PW), .stages(3)) u_csr2(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.din ( prev2_din ),
|
||||
.drop ( prev2 )
|
||||
);
|
||||
|
||||
|
||||
reg [ 10:0] subtresult;
|
||||
reg [OPW-1:0] shifter;
|
||||
wire signed [OPW-1:0] fb1 = prev[PW-1:OPW];
|
||||
wire signed [OPW-1:0] fb0 = prev[OPW-1:0];
|
||||
|
||||
// REGISTER/CYCLE 1
|
||||
// Creation of phase modulation (FM) feedback signal, before shifting
|
||||
reg signed [OPW-1:0] modmux_I;
|
||||
reg signed [OPW-1:0] fbmod_I;
|
||||
|
||||
always @(*) begin
|
||||
modmux_I = op_d ? op_result : fb1+fb0;
|
||||
// OPL-L shifts by 8-FB
|
||||
// OPL3 shifts by 9-FB
|
||||
// OPLL seems to use lower resolution for OPW so it makes
|
||||
// sense that it shifts by one fewer
|
||||
fbmod_I = modmux_I>>>(4'd9-{1'b0,fb_I_d});
|
||||
end
|
||||
|
||||
reg signed [9:0] phasemod_I;
|
||||
|
||||
always @(*) begin
|
||||
// Shift FM feedback signal
|
||||
if (op_d)
|
||||
phasemod_I = con_I_d ? 10'd0 : modmux_I[9:0];
|
||||
else
|
||||
phasemod_I = fb_I_d==3'd0 ? 10'd0 : fbmod_I[9:0];
|
||||
end
|
||||
|
||||
reg [ 9:0] phase;
|
||||
reg [ 7:0] aux_I;
|
||||
|
||||
always @(*) begin
|
||||
phase = phasemod_I + pg_phase_I;
|
||||
aux_I = phase[7:0] ^ {8{~phase[8]}};
|
||||
end
|
||||
|
||||
// REGISTER/CYCLE 1
|
||||
|
||||
always @(posedge clk) if( cenop ) begin
|
||||
if( OPL_TYPE==1 ) begin
|
||||
signbit_II <= phase[9];
|
||||
nullify_II <= 0;
|
||||
end else begin
|
||||
signbit_II <= wavsel_d==0 && phase[9];
|
||||
nullify_II <= (wavsel_d==2'b01 && phase[9]) || (wavsel_d==2'b11 && phase[8]);
|
||||
end
|
||||
end
|
||||
|
||||
wire [11:0] logsin_II;
|
||||
|
||||
jtopl_logsin u_logsin (
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.addr ( aux_I[7:0] ),
|
||||
.logsin ( logsin_II )
|
||||
);
|
||||
|
||||
// REGISTER/CYCLE 2
|
||||
// Sine table
|
||||
// Main sine table body
|
||||
|
||||
always @(*) begin
|
||||
subtresult = eg_atten_II + logsin_II[11:2];
|
||||
level_II = { subtresult[9:0], logsin_II[1:0] } | {12{subtresult[10]}};
|
||||
if( nullify_II ) begin
|
||||
level_II = ~12'h0;
|
||||
end
|
||||
end
|
||||
|
||||
wire [9:0] mantissa_III;
|
||||
reg [3:0] exponent_III;
|
||||
|
||||
jtopl_exprom u_exprom(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.addr ( level_II[7:0] ),
|
||||
.exp ( mantissa_III )
|
||||
);
|
||||
|
||||
always @(posedge clk) if( cenop ) begin
|
||||
exponent_III <= level_II[11:8];
|
||||
signbit_III <= signbit_II;
|
||||
end
|
||||
|
||||
// REGISTER/CYCLE 3
|
||||
// 2's complement & Carry-out discarded
|
||||
|
||||
always @(*) begin
|
||||
// Floating-point to integer, and incorporating sign bit
|
||||
shifter = { 2'b01, mantissa_III,1'b0 } >> exponent_III;
|
||||
end
|
||||
|
||||
// It looks like OPLL and OPL3 don't do full 2's complement but just bit inversion
|
||||
always @(posedge clk) if( cenop ) begin
|
||||
op_result <= ( shifter ^ {OPW{signbit_III}});// + {13'd0,signbit_III};
|
||||
end
|
||||
|
||||
`ifdef SIMULATION
|
||||
reg signed [OPW-1:0] op_sep0_0;
|
||||
reg signed [OPW-1:0] op_sep1_0;
|
||||
reg signed [OPW-1:0] op_sep2_0;
|
||||
reg signed [OPW-1:0] op_sep0_1;
|
||||
reg signed [OPW-1:0] op_sep1_1;
|
||||
reg signed [OPW-1:0] op_sep2_1;
|
||||
reg signed [OPW-1:0] op_sep4_0;
|
||||
reg signed [OPW-1:0] op_sep5_0;
|
||||
reg signed [OPW-1:0] op_sep6_0;
|
||||
reg signed [OPW-1:0] op_sep4_1;
|
||||
reg signed [OPW-1:0] op_sep5_1;
|
||||
reg signed [OPW-1:0] op_sep6_1;
|
||||
reg signed [OPW-1:0] op_sep7_0;
|
||||
reg signed [OPW-1:0] op_sep8_0;
|
||||
reg signed [OPW-1:0] op_sep9_0;
|
||||
reg signed [OPW-1:0] op_sep7_1;
|
||||
reg signed [OPW-1:0] op_sep8_1;
|
||||
reg signed [OPW-1:0] op_sep9_1;
|
||||
reg [ 4:0] sepcnt;
|
||||
|
||||
always @(posedge clk) if(cenop) begin
|
||||
sepcnt <= zero ? 5'd0 : sepcnt+5'd1;
|
||||
case( (sepcnt+3)%18 )
|
||||
0: op_sep0_0 <= op_result;
|
||||
1: op_sep1_0 <= op_result;
|
||||
2: op_sep2_0 <= op_result;
|
||||
3: op_sep0_1 <= op_result;
|
||||
4: op_sep1_1 <= op_result;
|
||||
5: op_sep2_1 <= op_result;
|
||||
6: op_sep4_0 <= op_result;
|
||||
7: op_sep5_0 <= op_result;
|
||||
8: op_sep6_0 <= op_result;
|
||||
9: op_sep4_1 <= op_result;
|
||||
10: op_sep5_1 <= op_result;
|
||||
11: op_sep6_1 <= op_result;
|
||||
12: op_sep7_0 <= op_result;
|
||||
13: op_sep8_0 <= op_result;
|
||||
14: op_sep9_0 <= op_result;
|
||||
15: op_sep7_1 <= op_result;
|
||||
16: op_sep8_1 <= op_result;
|
||||
17: op_sep9_1 <= op_result;
|
||||
endcase
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
129
common/Sound/ym3526/jtopl_pg.v
Normal file
129
common/Sound/ym3526/jtopl_pg.v
Normal file
@ -0,0 +1,129 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_pg(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cenop,
|
||||
input wire [17:0] slot,
|
||||
input wire rhy_en,
|
||||
// Channel frequency
|
||||
input wire [ 9:0] fnum_I,
|
||||
input wire [ 2:0] block_I,
|
||||
// Operator multiplying
|
||||
input wire [ 3:0] mul_II,
|
||||
// phase modulation from LFO (vibrato at 6.4Hz)
|
||||
input wire [ 2:0] vib_cnt,
|
||||
input wire vib_dep,
|
||||
input wire viben_I,
|
||||
// phase operation
|
||||
input wire pg_rst_II,
|
||||
|
||||
output reg [ 3:0] keycode_II,
|
||||
output wire [ 9:0] phase_IV
|
||||
);
|
||||
|
||||
parameter CH=9;
|
||||
|
||||
wire [ 3:0] keycode_I;
|
||||
wire [16:0] phinc_I;
|
||||
reg [16:0] phinc_II;
|
||||
wire [18:0] phase_drop, phase_in;
|
||||
wire [ 9:0] phase_II;
|
||||
wire noise;
|
||||
reg [ 9:0] hh, tc;
|
||||
reg rm_xor;
|
||||
wire hh_en, sd_en, tc_en;
|
||||
|
||||
always @(posedge clk) if(cenop) begin
|
||||
keycode_II <= keycode_I;
|
||||
phinc_II <= phinc_I;
|
||||
end
|
||||
|
||||
// Rhythm phase
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
hh <= 10'd0;
|
||||
tc <= 10'd0;
|
||||
end else begin
|
||||
if( slot[13] ) hh <= phase_drop[18:9];
|
||||
if( slot[17] ) tc <= phase_drop[18:9];
|
||||
rm_xor <= (hh[2]^hh[7]) | (hh[3]^tc[5]) | (tc[3]^tc[5]);
|
||||
end
|
||||
end
|
||||
|
||||
assign hh_en = rhy_en & slot[14]; // 13+1
|
||||
assign sd_en = rhy_en & slot[17]; // 16+1
|
||||
assign tc_en = rhy_en & slot[ 0]; // (17+1)%18
|
||||
|
||||
jtopl_noise u_noise(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.rst ( rst ),
|
||||
.noise ( noise )
|
||||
);
|
||||
|
||||
jtopl_pg_comb u_comb(
|
||||
.block ( block_I ),
|
||||
.fnum ( fnum_I ),
|
||||
// Phase Modulation
|
||||
.vib_cnt ( vib_cnt ),
|
||||
.vib_dep ( vib_dep ),
|
||||
.viben ( viben_I ),
|
||||
|
||||
.keycode ( keycode_I ),
|
||||
// Phase increment
|
||||
.phinc_out ( phinc_I ),
|
||||
// Phase add
|
||||
.mul ( mul_II ),
|
||||
.phase_in ( phase_drop ),
|
||||
.pg_rst ( pg_rst_II ),
|
||||
.phinc_in ( phinc_II ),
|
||||
// Rhythm
|
||||
.hh_en ( hh_en ),
|
||||
.sd_en ( sd_en ),
|
||||
.tc_en ( tc_en ),
|
||||
.rm_xor ( rm_xor ),
|
||||
.noise ( noise ),
|
||||
.hh ( hh ),
|
||||
|
||||
.phase_out ( phase_in ),
|
||||
.phase_op ( phase_II )
|
||||
);
|
||||
|
||||
jtopl_sh_rst #( .width(19), .stages(2*CH) ) u_phsh(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.rst ( rst ),
|
||||
.din ( phase_in ),
|
||||
.drop ( phase_drop)
|
||||
);
|
||||
|
||||
jtopl_sh_rst #( .width(10), .stages(2) ) u_pad(
|
||||
.clk ( clk ),
|
||||
.cen ( cenop ),
|
||||
.rst ( rst ),
|
||||
.din ( phase_II ),
|
||||
.drop ( phase_IV )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
95
common/Sound/ym3526/jtopl_pg_comb.v
Normal file
95
common/Sound/ym3526/jtopl_pg_comb.v
Normal file
@ -0,0 +1,95 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_pg_comb (
|
||||
input wire [ 2:0] block,
|
||||
input wire [ 9:0] fnum,
|
||||
// Phase Modulation
|
||||
input wire [ 2:0] vib_cnt,
|
||||
input wire vib_dep,
|
||||
input wire viben,
|
||||
|
||||
output wire [ 3:0] keycode,
|
||||
// Phase increment
|
||||
output wire [16:0] phinc_out,
|
||||
// Phase add
|
||||
input wire [ 3:0] mul,
|
||||
input wire [18:0] phase_in,
|
||||
input wire pg_rst,
|
||||
// input signed [7:0] pm_in,
|
||||
input wire [16:0] phinc_in,
|
||||
// Rhythm
|
||||
input wire noise,
|
||||
input wire [ 9:0] hh,
|
||||
input wire hh_en,
|
||||
input wire tc_en,
|
||||
input wire sd_en,
|
||||
input wire rm_xor,
|
||||
|
||||
output wire [18:0] phase_out,
|
||||
output wire [ 9:0] phase_op
|
||||
);
|
||||
|
||||
wire signed [3:0] pm_offset;
|
||||
wire [9:0] phase_pre;
|
||||
|
||||
assign keycode = { block, fnum[9] };
|
||||
|
||||
/* pm and pg_inc operate in parallel */
|
||||
jtopl_pm u_pm(
|
||||
.vib_cnt ( vib_cnt ),
|
||||
.fnum ( fnum ),
|
||||
.vib_dep ( vib_dep ),
|
||||
.viben ( viben ),
|
||||
.pm_offset ( pm_offset )
|
||||
);
|
||||
|
||||
jtopl_pg_inc u_inc(
|
||||
.block ( block ),
|
||||
.fnum ( fnum ),
|
||||
.pm_offset ( pm_offset ),
|
||||
.phinc_pure ( phinc_out )
|
||||
);
|
||||
|
||||
// pg_sum uses the output from the previous blocks
|
||||
|
||||
jtopl_pg_sum u_sum(
|
||||
.mul ( mul ),
|
||||
.phase_in ( phase_in ),
|
||||
.pg_rst ( pg_rst ),
|
||||
.phinc_pure ( phinc_in ),
|
||||
.phase_out ( phase_out ),
|
||||
.phase_op ( phase_pre )
|
||||
);
|
||||
|
||||
jtopl_pg_rhy u_rhy(
|
||||
.phase_pre ( phase_pre ),
|
||||
// Rhythm
|
||||
.noise ( noise ),
|
||||
.hh ( hh ),
|
||||
.hh_en ( hh_en ),
|
||||
.tc_en ( tc_en ),
|
||||
.sd_en ( sd_en ),
|
||||
.rm_xor ( rm_xor ),
|
||||
.phase_op ( phase_op )
|
||||
);
|
||||
|
||||
endmodule // jtopl_pg_comb
|
||||
38
common/Sound/ym3526/jtopl_pg_inc.v
Normal file
38
common/Sound/ym3526/jtopl_pg_inc.v
Normal file
@ -0,0 +1,38 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_pg_inc (
|
||||
input wire [ 2:0] block,
|
||||
input wire [ 9:0] fnum,
|
||||
input wire signed [ 3:0] pm_offset,
|
||||
output reg [16:0] phinc_pure
|
||||
);
|
||||
|
||||
reg [16:0] freq;
|
||||
|
||||
always @(*) begin
|
||||
freq = { 7'd0, fnum } + { {13{pm_offset[3]}}, pm_offset };
|
||||
// Add PM here
|
||||
freq = freq << block;
|
||||
phinc_pure = freq >> 1;
|
||||
end
|
||||
|
||||
endmodule // jtopl_pg_inc
|
||||
49
common/Sound/ym3526/jtopl_pg_rhy.v
Normal file
49
common/Sound/ym3526/jtopl_pg_rhy.v
Normal file
@ -0,0 +1,49 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 25-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_pg_rhy (
|
||||
input wire [ 9:0] phase_pre,
|
||||
// Rhythm
|
||||
input wire noise,
|
||||
input wire [ 9:0] hh,
|
||||
input wire hh_en,
|
||||
input wire tc_en,
|
||||
input wire sd_en,
|
||||
input wire rm_xor,
|
||||
output reg [ 9:0] phase_op
|
||||
);
|
||||
|
||||
always @(*) begin
|
||||
if( hh_en ) begin
|
||||
phase_op = {rm_xor, 9'd0 };
|
||||
if( rm_xor ^ noise )
|
||||
phase_op = phase_op | 10'hd0;
|
||||
else
|
||||
phase_op = phase_op | 10'h34;
|
||||
end else if( sd_en ) begin
|
||||
phase_op = { hh[8], hh[8]^noise, 8'd0 };
|
||||
end else if( tc_en ) begin
|
||||
phase_op = { rm_xor, 9'h80 };
|
||||
end else
|
||||
phase_op = phase_pre;
|
||||
end
|
||||
|
||||
endmodule // jtopl_pg_sum
|
||||
52
common/Sound/ym3526/jtopl_pg_sum.v
Normal file
52
common/Sound/ym3526/jtopl_pg_sum.v
Normal file
@ -0,0 +1,52 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
|
||||
*/
|
||||
|
||||
// Original hardware uses an adder to do the multiplication
|
||||
// but I think it will take less resources of the FPGA to
|
||||
// use a real multiplier instead
|
||||
|
||||
module jtopl_pg_sum (
|
||||
input wire [ 3:0] mul,
|
||||
input wire [18:0] phase_in,
|
||||
input wire pg_rst,
|
||||
input wire [16:0] phinc_pure,
|
||||
|
||||
output reg [18:0] phase_out,
|
||||
output reg [ 9:0] phase_op
|
||||
);
|
||||
|
||||
reg [21:0] phinc_mul;
|
||||
reg [ 4:0] factor[0:15];
|
||||
|
||||
always @(*) begin
|
||||
phinc_mul = { 5'b0, phinc_pure} * factor[mul];
|
||||
phase_out = pg_rst ? 'd0 : (phase_in + phinc_mul[19:1]);
|
||||
phase_op = phase_out[18:9];
|
||||
end
|
||||
|
||||
initial begin
|
||||
factor[ 0] = 5'd01; factor[ 1] = 5'd02; factor[ 2] = 5'd04; factor[ 3] = 5'd06;
|
||||
factor[ 4] = 5'd08; factor[ 5] = 5'd10; factor[ 6] = 5'd12; factor[ 7] = 5'd14;
|
||||
factor[ 8] = 5'd16; factor[ 9] = 5'd18; factor[10] = 5'd20; factor[11] = 5'd20;
|
||||
factor[12] = 5'd24; factor[13] = 5'd24; factor[14] = 5'd30; factor[15] = 5'd30;
|
||||
end
|
||||
|
||||
endmodule // jtopl_pg_sum
|
||||
47
common/Sound/ym3526/jtopl_pm.v
Normal file
47
common/Sound/ym3526/jtopl_pm.v
Normal file
@ -0,0 +1,47 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 21-6-2020
|
||||
*/
|
||||
|
||||
// Based on Nuked's work on OPLL and OPL3
|
||||
|
||||
module jtopl_pm (
|
||||
input wire [ 2:0] vib_cnt,
|
||||
input wire [ 9:0] fnum,
|
||||
input wire vib_dep,
|
||||
input wire viben,
|
||||
output reg [ 3:0] pm_offset
|
||||
);
|
||||
|
||||
reg [2:0] range;
|
||||
|
||||
always @(*) begin
|
||||
if( vib_cnt[1:0]==2'b00 )
|
||||
range = 3'd0;
|
||||
else begin
|
||||
range = fnum[9:7]>>vib_cnt[0];
|
||||
if(!vib_dep) range = range>>1;
|
||||
end
|
||||
if( vib_cnt[2] )
|
||||
pm_offset = ~{1'b0, range } + 4'd1;
|
||||
else
|
||||
pm_offset = {1'b0, range };
|
||||
if(!viben) pm_offset = 4'd0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
270
common/Sound/ym3526/jtopl_reg.v
Normal file
270
common/Sound/ym3526/jtopl_reg.v
Normal file
@ -0,0 +1,270 @@
|
||||
/* This file is part of JTOPL
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_reg #(parameter OPL_TYPE=1)
|
||||
(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
input wire [7:0] din,
|
||||
input wire write,
|
||||
// Pipeline order
|
||||
output wire zero,
|
||||
output reg [1:0] group,
|
||||
output reg op, // 0 for modulator operators
|
||||
output reg [17:0] slot, // hot one encoding of active slot
|
||||
|
||||
input wire [1:0] sel_group, // group to update
|
||||
input wire [2:0] sel_sub, // subslot to update
|
||||
|
||||
input wire rhy_en, // rhythm enable
|
||||
input wire [4:0] rhy_kon, // key-on for each rhythm instrument
|
||||
|
||||
//input csm,
|
||||
//input flag_A,
|
||||
//input overflow_A,
|
||||
|
||||
input wire up_fbcon,
|
||||
input wire up_fnumlo,
|
||||
input wire up_fnumhi,
|
||||
input wire up_mult,
|
||||
input wire up_ksl_tl,
|
||||
input wire up_ar_dr,
|
||||
input wire up_sl_rr,
|
||||
input wire up_wav,
|
||||
|
||||
// PG
|
||||
output wire [9:0] fnum_I,
|
||||
output wire [2:0] block_I,
|
||||
// channel configuration
|
||||
output wire [2:0] fb_I,
|
||||
|
||||
output wire [3:0] mul_II, // frequency multiplier
|
||||
output wire [1:0] ksl_IV, // key shift level
|
||||
output wire amen_IV,
|
||||
output wire viben_I,
|
||||
// OP
|
||||
output wire [1:0] wavsel_I,
|
||||
input wire wave_mode,
|
||||
// EG
|
||||
output wire keyon_I,
|
||||
output wire [5:0] tl_IV,
|
||||
output wire en_sus_I, // enable sustain
|
||||
output wire [3:0] arate_I, // attack rate
|
||||
output wire [3:0] drate_I, // decay rate
|
||||
output wire [3:0] rrate_I, // release rate
|
||||
output wire [3:0] sl_I, // sustain level
|
||||
output wire ks_II, // key scale
|
||||
output wire con_I
|
||||
);
|
||||
|
||||
//parameter OPL_TYPE=1;
|
||||
|
||||
localparam CH=9;
|
||||
|
||||
// Each group contains three channels
|
||||
// and each subslot contains six operators
|
||||
reg [2:0] subslot;
|
||||
|
||||
reg [5:0] rhy_csr;
|
||||
reg rhy_oen;
|
||||
|
||||
`ifdef SIMULATION
|
||||
// These signals need to operate during rst
|
||||
// initial state is not relevant (or critical) in real life
|
||||
// but we need a clear value during simulation
|
||||
initial begin
|
||||
group = 2'd0;
|
||||
subslot = 3'd0;
|
||||
slot = 18'd1;
|
||||
end
|
||||
`endif
|
||||
|
||||
wire match = { group, subslot } == { sel_group, sel_sub};
|
||||
wire [2:0] next_sub = subslot==3'd5 ? 3'd0 : (subslot+3'd1);
|
||||
wire [1:0] next_group = subslot==3'd5 ? (group==2'b10 ? 2'b00 : group+2'b1) : group;
|
||||
|
||||
|
||||
// channel data
|
||||
wire [2:0] fb_in = din[3:1];
|
||||
wire con_in = din[0];
|
||||
|
||||
wire up_fnumlo_ch = up_fnumlo & match,
|
||||
up_fnumhi_ch = up_fnumhi & match,
|
||||
up_fbcon_ch = up_fbcon & match,
|
||||
update_op_I = !write && sel_group == group && sel_sub == subslot;
|
||||
|
||||
reg update_op_II, update_op_III, update_op_IV;
|
||||
|
||||
assign zero = slot[0];
|
||||
|
||||
always @(posedge clk) begin : up_counter
|
||||
if( cen ) begin
|
||||
{ group, subslot } <= { next_group, next_sub };
|
||||
if( { next_group, next_sub }==5'd0 ) begin
|
||||
slot <= 18'd1;
|
||||
end else begin
|
||||
slot <= { slot[16:0], 1'b0 };
|
||||
end
|
||||
op <= next_sub >= 3'd3;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(write) begin
|
||||
update_op_II <= 0;
|
||||
update_op_III <= 0;
|
||||
update_op_IV <= 0;
|
||||
end else if( cen ) begin
|
||||
update_op_II <= update_op_I;
|
||||
update_op_III <= update_op_II;
|
||||
update_op_IV <= update_op_III;
|
||||
end
|
||||
end
|
||||
|
||||
localparam OPCFGW = 4*8 + (OPL_TYPE!=1 ? 2 : 0);
|
||||
|
||||
wire [OPCFGW-1:0] shift_out;
|
||||
wire en_sus;
|
||||
|
||||
// Sustained is disabled in rhythm mode for channels in group 2 (i.e. 6,7,8)
|
||||
assign en_sus_I = rhy_oen ? 1'b0 : en_sus;
|
||||
|
||||
jtopl_csr #(.LEN(CH*2),.W(OPCFGW)) u_csr(
|
||||
.rst ( rst ),
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.din ( din ),
|
||||
.shift_out ( shift_out ),
|
||||
.up_mult ( up_mult ),
|
||||
.up_ksl_tl ( up_ksl_tl ),
|
||||
.up_ar_dr ( up_ar_dr ),
|
||||
.up_sl_rr ( up_sl_rr ),
|
||||
.up_wav ( up_wav ),
|
||||
.update_op_I ( update_op_I ),
|
||||
.update_op_II ( update_op_II ),
|
||||
.update_op_IV ( update_op_IV )
|
||||
);
|
||||
|
||||
assign { amen_IV, viben_I, en_sus, ks_II, mul_II,
|
||||
ksl_IV, tl_IV,
|
||||
arate_I, drate_I,
|
||||
sl_I, rrate_I } = shift_out[4*8-1:0];
|
||||
|
||||
generate
|
||||
if( OPL_TYPE==1 )
|
||||
assign wavsel_I = 0;
|
||||
else
|
||||
assign wavsel_I = shift_out[OPCFGW-1:OPCFGW-2] & {2{wave_mode}};
|
||||
endgenerate
|
||||
|
||||
|
||||
// Memory for CH registers
|
||||
localparam KONW = 1,
|
||||
FNUMW = 10,
|
||||
BLOCKW = 3,
|
||||
FBW = 3,
|
||||
CONW = 1;
|
||||
localparam CHCSRW = KONW+FNUMW+BLOCKW+FBW+CONW;
|
||||
|
||||
wire [CHCSRW-1:0] chcfg0_out, chcfg1_out, chcfg2_out;
|
||||
reg [CHCSRW-1:0] chcfg, chcfg0_in, chcfg1_in, chcfg2_in;
|
||||
wire [CHCSRW-1:0] chcfg_inmux;
|
||||
wire keyon_csr, con_csr;
|
||||
wire disable_con;
|
||||
|
||||
assign chcfg_inmux = {
|
||||
up_fnumhi_ch ? din[5:0] : { keyon_csr, block_I, fnum_I[9:8] },
|
||||
up_fnumlo_ch ? din : fnum_I[7:0],
|
||||
up_fbcon_ch ? { fb_in, con_in } : { fb_I, con_csr }
|
||||
};
|
||||
|
||||
assign disable_con = rhy_oen && !slot[12] && !slot[13];
|
||||
assign con_I = !rhy_en || !disable_con ? con_csr : 1'b1;
|
||||
|
||||
always @(*) begin
|
||||
case( group )
|
||||
default: chcfg = chcfg0_out;
|
||||
2'd1: chcfg = chcfg1_out;
|
||||
2'd2: chcfg = chcfg2_out;
|
||||
endcase
|
||||
chcfg0_in = group==2'b00 ? chcfg_inmux : chcfg0_out;
|
||||
chcfg1_in = group==2'b01 ? chcfg_inmux : chcfg1_out;
|
||||
chcfg2_in = group==2'b10 ? chcfg_inmux : chcfg2_out;
|
||||
end
|
||||
|
||||
`ifdef SIMULATION
|
||||
reg [CHCSRW-1:0] chsnap0, chsnap1,chsnap2;
|
||||
|
||||
always @(posedge clk) if(zero) begin
|
||||
chsnap0 <= chcfg0_out;
|
||||
chsnap1 <= chcfg1_out;
|
||||
chsnap2 <= chcfg2_out;
|
||||
end
|
||||
`endif
|
||||
|
||||
assign { keyon_csr, block_I, fnum_I, fb_I, con_csr } = chcfg;
|
||||
|
||||
// Rhythm key-on CSR
|
||||
localparam BD=4, SD=3, TOM=2, TC=1, HH=0;
|
||||
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
rhy_csr <= 6'd0;
|
||||
rhy_oen <= 0;
|
||||
end else if(cen) begin
|
||||
if(slot[11]) rhy_oen <= rhy_en;
|
||||
if(slot[17]) begin
|
||||
rhy_csr <= { rhy_kon[BD], rhy_kon[HH], rhy_kon[TOM],
|
||||
rhy_kon[BD], rhy_kon[SD], rhy_kon[TC] };
|
||||
rhy_oen <= 0;
|
||||
end else
|
||||
rhy_csr <= { rhy_csr[4:0], rhy_csr[5] };
|
||||
end
|
||||
end
|
||||
|
||||
assign keyon_I = rhy_oen ? rhy_csr[5] : keyon_csr;
|
||||
|
||||
jtopl_sh_rst #(.width(CHCSRW),.stages(3)) u_group0(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.rst ( rst ),
|
||||
.din ( chcfg0_in ),
|
||||
.drop ( chcfg0_out )
|
||||
);
|
||||
|
||||
jtopl_sh_rst #(.width(CHCSRW),.stages(3)) u_group1(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.rst ( rst ),
|
||||
.din ( chcfg1_in ),
|
||||
.drop ( chcfg1_out )
|
||||
);
|
||||
|
||||
jtopl_sh_rst #(.width(CHCSRW),.stages(3)) u_group2(
|
||||
.clk ( clk ),
|
||||
.cen ( cen ),
|
||||
.rst ( rst ),
|
||||
.din ( chcfg2_in ),
|
||||
.drop ( chcfg2_out )
|
||||
);
|
||||
|
||||
endmodule
|
||||
42
common/Sound/ym3526/jtopl_sh.v
Normal file
42
common/Sound/ym3526/jtopl_sh.v
Normal file
@ -0,0 +1,42 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 19-6-2020
|
||||
*/
|
||||
|
||||
// stages must be greater than 2
|
||||
module jtopl_sh #(parameter width=5, stages=24 )
|
||||
(
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
input wire [width-1:0] din,
|
||||
output wire [width-1:0] drop
|
||||
);
|
||||
|
||||
reg [stages-1:0] bits[width-1:0];
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < width; i=i+1) begin: bit_shifter
|
||||
always @(posedge clk) if(cen) begin
|
||||
bits[i] <= {bits[i][stages-2:0], din[i]};
|
||||
end
|
||||
assign drop[i] = bits[i][stages-1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
54
common/Sound/ym3526/jtopl_sh_rst.v
Normal file
54
common/Sound/ym3526/jtopl_sh_rst.v
Normal file
@ -0,0 +1,54 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 13-6-2020
|
||||
*/
|
||||
|
||||
// stages must be greater than 2
|
||||
module jtopl_sh_rst #(parameter width=5, stages=18, rstval=1'b0 )
|
||||
(
|
||||
input wire rst,
|
||||
input wire clk,
|
||||
input wire cen,
|
||||
input wire [width-1:0] din,
|
||||
output wire [width-1:0] drop
|
||||
);
|
||||
|
||||
reg [stages-1:0] bits[width-1:0];
|
||||
|
||||
genvar i;
|
||||
integer k;
|
||||
generate
|
||||
initial
|
||||
for (k=0; k < width; k=k+1) begin
|
||||
bits[k] = { stages{rstval}};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
for (i=0; i < width; i=i+1) begin: bit_shifter
|
||||
always @(posedge clk, posedge rst)
|
||||
if( rst ) begin
|
||||
bits[i] <= {stages{rstval}};
|
||||
end else if(cen) begin
|
||||
bits[i] <= {bits[i][stages-2:0], din[i]};
|
||||
end
|
||||
assign drop[i] = bits[i][stages-1];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
61
common/Sound/ym3526/jtopl_single_acc.v
Normal file
61
common/Sound/ym3526/jtopl_single_acc.v
Normal file
@ -0,0 +1,61 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
|
||||
JTOPL program 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.
|
||||
|
||||
JTOPL program 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 20-6-2020
|
||||
|
||||
*/
|
||||
|
||||
// Accumulates an arbitrary number of inputs with saturation
|
||||
// restart the sum when input "zero" is high
|
||||
|
||||
module jtopl_single_acc #(parameter
|
||||
INW=13, // input data width
|
||||
OUTW=16 // output data width
|
||||
)(
|
||||
input wire clk,
|
||||
input wire cenop,
|
||||
input wire [INW-1:0] op_result,
|
||||
input wire sum_en,
|
||||
input wire zero,
|
||||
output reg [OUTW-1:0] snd
|
||||
);
|
||||
|
||||
// for full resolution use INW=14, OUTW=16
|
||||
// for cut down resolution use INW=9, OUTW=12
|
||||
// OUTW-INW should be > 0
|
||||
|
||||
reg signed [OUTW-1:0] next, acc, current;
|
||||
reg overflow;
|
||||
|
||||
wire [OUTW-1:0] plus_inf = { 1'b0, {(OUTW-1){1'b1}} }; // maximum positive value
|
||||
wire [OUTW-1:0] minus_inf = { 1'b1, {(OUTW-1){1'b0}} }; // minimum negative value
|
||||
|
||||
always @(*) begin
|
||||
current = sum_en ? { {(OUTW-INW){op_result[INW-1]}}, op_result } : {OUTW{1'b0}};
|
||||
next = zero ? current : current + acc;
|
||||
overflow = !zero &&
|
||||
(current[OUTW-1] == acc[OUTW-1]) &&
|
||||
(acc[OUTW-1]!=next[OUTW-1]);
|
||||
end
|
||||
|
||||
always @(posedge clk) if( cenop ) begin
|
||||
acc <= overflow ? (acc[OUTW-1] ? minus_inf : plus_inf) : next;
|
||||
if(zero) snd <= acc;
|
||||
end
|
||||
|
||||
endmodule
|
||||
125
common/Sound/ym3526/jtopl_timers.v
Normal file
125
common/Sound/ym3526/jtopl_timers.v
Normal file
@ -0,0 +1,125 @@
|
||||
/* This file is part of JTOPL.
|
||||
|
||||
JTOPL 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.
|
||||
|
||||
JTOPL 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 JTOPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 10-6-2020
|
||||
|
||||
*/
|
||||
|
||||
module jtopl_timers(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
input wire cenop,
|
||||
input wire zero,
|
||||
input wire [7:0] value_A,
|
||||
input wire [7:0] value_B,
|
||||
input wire load_A,
|
||||
input wire load_B,
|
||||
input wire clr_flag_A,
|
||||
input wire clr_flag_B,
|
||||
output wire flag_A,
|
||||
output wire flag_B,
|
||||
input wire flagen_A,
|
||||
input wire flagen_B,
|
||||
output wire overflow_A,
|
||||
output wire irq_n
|
||||
);
|
||||
|
||||
wire pre_A, pre_B;
|
||||
|
||||
assign flag_A = pre_A & flagen_A;
|
||||
assign flag_B = pre_B & flagen_B;
|
||||
|
||||
assign irq_n = ~( flag_A | flag_B );
|
||||
|
||||
// 1 count per 288 master clock ticks
|
||||
jtopl_timer #(.MW(2)) timer_A (
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.cenop ( cenop ),
|
||||
.zero ( zero ),
|
||||
.start_value( value_A ),
|
||||
.load ( load_A ),
|
||||
.clr_flag ( clr_flag_A),
|
||||
.flag ( pre_A ),
|
||||
.overflow ( overflow_A)
|
||||
);
|
||||
|
||||
// 1 count per 288*4 master clock ticks
|
||||
jtopl_timer #(.MW(4)) timer_B(
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.cenop ( cenop ),
|
||||
.zero ( zero ),
|
||||
.start_value( value_B ),
|
||||
.load ( load_B ),
|
||||
.clr_flag ( clr_flag_B),
|
||||
.flag ( pre_B ),
|
||||
.overflow ( )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module jtopl_timer #(parameter MW=2) (
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
input wire cenop,
|
||||
input wire zero,
|
||||
input wire [7:0] start_value,
|
||||
input wire load,
|
||||
input wire clr_flag,
|
||||
output reg flag,
|
||||
output reg overflow
|
||||
);
|
||||
|
||||
reg [7:0] cnt, next, init;
|
||||
reg [MW-1:0] free_cnt, free_next;
|
||||
reg load_l, free_ov;
|
||||
|
||||
always@(posedge clk)
|
||||
if( clr_flag || rst)
|
||||
flag <= 1'b0;
|
||||
else if(cenop && zero && load && overflow) flag<=1'b1;
|
||||
|
||||
always @(*) begin
|
||||
{free_ov, free_next} = { 1'b0, free_cnt} + 1'b1;
|
||||
/* verilator lint_off WIDTH */
|
||||
{overflow, next } = {1'b0, cnt}+free_ov;
|
||||
/* verilator lint_on WIDTH */
|
||||
init = start_value;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
load_l <= load;
|
||||
if( (!load_l && load) || rst) begin
|
||||
cnt <= start_value;
|
||||
end else if( cenop && zero && load ) begin
|
||||
cnt <= overflow ? init : next;
|
||||
end
|
||||
end
|
||||
|
||||
// Free running counter, resetting
|
||||
// the value of this part with the load
|
||||
// event can slow down music, vg Bad Dudes
|
||||
always @(posedge clk) begin
|
||||
if( rst ) begin
|
||||
free_cnt <= 0;
|
||||
end else if( cenop && zero ) begin
|
||||
free_cnt <= free_next;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
BIN
common/mra.exe
BIN
common/mra.exe
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user