mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-19 07:11:22 +03:00
Update turbosound.
This commit is contained in:
@ -12,9 +12,8 @@ set_global_assignment -name VERILOG_FILE rtl/common/zint.v
|
|||||||
set_global_assignment -name VERILOG_FILE rtl/common/zclock.v
|
set_global_assignment -name VERILOG_FILE rtl/common/zclock.v
|
||||||
set_global_assignment -name VERILOG_FILE rtl/rtc/mc146818a.v
|
set_global_assignment -name VERILOG_FILE rtl/rtc/mc146818a.v
|
||||||
set_global_assignment -name VHDL_FILE rtl/sound/soundrive.vhd
|
set_global_assignment -name VHDL_FILE rtl/sound/soundrive.vhd
|
||||||
set_global_assignment -name QIP_FILE rtl/sound/jt12/jt12.qip
|
set_global_assignment -name QIP_FILE rtl/sound/jt12/jt03.qip
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/ym2149.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/ym2149.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/ym2203.sv
|
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/turbosound.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/turbosound.sv
|
||||||
set_global_assignment -name VERILOG_FILE rtl/sound/gs.v
|
set_global_assignment -name VERILOG_FILE rtl/sound/gs.v
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/saa1099.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/saa1099.sv
|
||||||
|
@ -1,21 +1,34 @@
|
|||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_acc.v ]
|
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) jt12.vhd ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_clksync.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_top.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03_acc.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_single_acc.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_cnt.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_comb.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_step.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_pure.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_final.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_eg_ctrl.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_exprom.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_kon.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_lfo.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_limitamp.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_limitamp.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mmr.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_div.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_mod.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_op.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_opram.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_csr.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_phrom.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_inc.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_dt.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_sum.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pg_comb.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_pm.v ]
|
||||||
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_logsin.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_reg.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh_rst.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sh24.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_sumch.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_syn.v ]
|
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_timers.v ]
|
73
rtl/sound/jt12/jt03.v
Normal file
73
rtl/sound/jt12/jt03.v
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 27-12-2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Wrapper to output only combined channels. Defaults to YM2203 mode.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module jt03(
|
||||||
|
input rst, // rst should be at least 6 clk&cen cycles long
|
||||||
|
input clk, // CPU clock
|
||||||
|
input cen, // optional clock enable, it not needed leave as 1'b1
|
||||||
|
input [7:0] din,
|
||||||
|
input addr,
|
||||||
|
input cs_n,
|
||||||
|
input wr_n,
|
||||||
|
|
||||||
|
output [7:0] dout,
|
||||||
|
output irq_n,
|
||||||
|
// Separated output
|
||||||
|
output [ 7:0] psg_A,
|
||||||
|
output [ 7:0] psg_B,
|
||||||
|
output [ 7:0] psg_C,
|
||||||
|
output signed [15:0] fm_snd,
|
||||||
|
// combined output
|
||||||
|
output [ 9:0] psg_snd,
|
||||||
|
output signed [15:0] snd,
|
||||||
|
output snd_sample
|
||||||
|
);
|
||||||
|
|
||||||
|
jt12_top #(.use_lfo(0),.use_ssg(1), .num_ch(3), .use_pcm(0), .use_lr(0))
|
||||||
|
u_jt12(
|
||||||
|
.rst ( rst ), // rst should be at least 6 clk&cen cycles long
|
||||||
|
.clk ( clk ), // CPU clock
|
||||||
|
.cen ( cen ), // optional clock enable, it not needed leave as 1'b1
|
||||||
|
.din ( din ),
|
||||||
|
.addr ( {1'b0, addr} ),
|
||||||
|
.cs_n ( cs_n ),
|
||||||
|
.wr_n ( wr_n ),
|
||||||
|
|
||||||
|
.dout ( dout ),
|
||||||
|
.irq_n ( irq_n ),
|
||||||
|
// Separated output
|
||||||
|
.psg_A ( psg_A ),
|
||||||
|
.psg_B ( psg_B ),
|
||||||
|
.psg_C ( psg_C ),
|
||||||
|
.psg_snd ( psg_snd ),
|
||||||
|
.fm_snd_left ( fm_snd ),
|
||||||
|
.fm_snd_right (),
|
||||||
|
|
||||||
|
.snd_right ( snd ),
|
||||||
|
.snd_left (),
|
||||||
|
.snd_sample ( snd_sample )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule // jt03
|
66
rtl/sound/jt12/jt03_acc.v
Normal file
66
rtl/sound/jt12/jt03_acc.v
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 15-11-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
/* Use for YM2203
|
||||||
|
no left/right channels
|
||||||
|
full operator resolution
|
||||||
|
clamped to maximum output of signed 16 bits */
|
||||||
|
|
||||||
|
module jt03_acc
|
||||||
|
(
|
||||||
|
input rst,
|
||||||
|
input clk,
|
||||||
|
input clk_en,
|
||||||
|
input signed [13:0] op_result,
|
||||||
|
input s1_enters,
|
||||||
|
input s2_enters,
|
||||||
|
input s3_enters,
|
||||||
|
input s4_enters,
|
||||||
|
input zero,
|
||||||
|
input [2:0] alg,
|
||||||
|
// combined output
|
||||||
|
output signed [15:0] snd
|
||||||
|
);
|
||||||
|
|
||||||
|
reg sum_en;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
case ( alg )
|
||||||
|
default: sum_en = s4_enters;
|
||||||
|
3'd4: sum_en = s2_enters | s4_enters;
|
||||||
|
3'd5,3'd6: sum_en = ~s1_enters;
|
||||||
|
3'd7: sum_en = 1'b1;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
jt12_single_acc #(.win(14),.wout(16)) u_mono(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.op_result ( op_result ),
|
||||||
|
.sum_en ( sum_en ),
|
||||||
|
.zero ( zero ),
|
||||||
|
.snd ( snd )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
@ -1,6 +1,3 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of JT12.
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
@ -17,100 +14,52 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with JT12. If not, see <http://www.gnu.org/licenses/>.
|
along with JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Based on information provided by
|
|
||||||
Sauraen VHDL version of OPN/OPN2, which is based on die shots.
|
|
||||||
Nemesis reports, based on measurements
|
|
||||||
Comparisons with real hardware lent by Mikes (Va de retro)
|
|
||||||
|
|
||||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
Version: 1.0
|
Version: 1.0
|
||||||
Date: 1-4-2017
|
Date: 27-12-2018
|
||||||
|
|
||||||
Use tab = 4 spaces
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// syn_clk "1.285714"
|
// Wrapper to output only combined channels. Defaults to YM2612 mode.
|
||||||
|
|
||||||
module jt12 (
|
module jt12 (
|
||||||
input rst,
|
input rst, // rst should be at least 6 clk&cen cycles long
|
||||||
// CPU interface
|
input clk, // CPU clock
|
||||||
input cpu_clk,
|
input cen, // optional clock enable, it not needed leave as 1'b1
|
||||||
input [7:0] cpu_din,
|
input [7:0] din,
|
||||||
input [1:0] cpu_addr,
|
input [1:0] addr,
|
||||||
input cpu_cs_n,
|
input cs_n,
|
||||||
input cpu_wr_n,
|
input wr_n,
|
||||||
input cpu_limiter_en,
|
|
||||||
|
|
||||||
output [7:0] cpu_dout,
|
output [7:0] dout,
|
||||||
output cpu_irq_n,
|
output irq_n,
|
||||||
// Synthesizer clock domain
|
|
||||||
input syn_clk,
|
|
||||||
// combined output
|
// combined output
|
||||||
output signed [11:0] syn_snd_right,
|
output signed [15:0] snd_right,
|
||||||
output signed [11:0] syn_snd_left,
|
output signed [15:0] snd_left,
|
||||||
output syn_snd_sample,
|
output snd_sample
|
||||||
// multiplexed output
|
|
||||||
output signed [8:0] syn_mux_right,
|
|
||||||
output signed [8:0] syn_mux_left,
|
|
||||||
output syn_mux_sample
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Timers
|
jt12_top u_jt12(
|
||||||
wire syn_flag_A, syn_flag_B;
|
.rst ( rst ), // rst should be at least 6 clk&cen cycles long
|
||||||
|
.clk ( clk ), // CPU clock
|
||||||
|
.cen ( cen ), // optional clock enable, it not needed leave as 1'b1
|
||||||
|
.din ( din ),
|
||||||
|
.addr ( addr ),
|
||||||
|
.cs_n ( cs_n ),
|
||||||
|
.wr_n ( wr_n ),
|
||||||
|
|
||||||
|
.dout ( dout ),
|
||||||
wire [7:0] syn_din;
|
.irq_n ( irq_n ),
|
||||||
wire [1:0] syn_addr;
|
// Separated output
|
||||||
wire syn_write, syn_limiter_en, syn_busy;
|
.psg_A (),
|
||||||
wire syn_rst, syn_irq_n;
|
.psg_B (),
|
||||||
|
.psg_C (),
|
||||||
jt12_clksync u_clksync(
|
.fm_snd_left (),
|
||||||
.rst ( rst ),
|
.fm_snd_right (),
|
||||||
.cpu_clk ( cpu_clk ),
|
// combined output
|
||||||
.syn_clk ( syn_clk ),
|
.psg_snd (),
|
||||||
|
.snd_right ( snd_right ), // FM+PSG
|
||||||
// CPU interface
|
.snd_left ( snd_left ), // FM+PSG
|
||||||
.cpu_din ( cpu_din ),
|
.snd_sample ( snd_sample )
|
||||||
.cpu_addr ( cpu_addr ),
|
|
||||||
.cpu_dout ( cpu_dout ),
|
|
||||||
.cpu_cs_n ( cpu_cs_n ),
|
|
||||||
.cpu_wr_n ( cpu_wr_n ),
|
|
||||||
.cpu_irq_n ( cpu_irq_n ),
|
|
||||||
.cpu_limiter_en( cpu_limiter_en ),
|
|
||||||
|
|
||||||
// Synthesizer interface
|
|
||||||
.syn_rst ( syn_rst ),
|
|
||||||
.syn_write ( syn_write ),
|
|
||||||
.syn_din ( syn_din ),
|
|
||||||
.syn_addr ( syn_addr ),
|
|
||||||
.syn_limiter_en( syn_limiter_en ),
|
|
||||||
|
|
||||||
.syn_busy ( syn_busy ),
|
|
||||||
.syn_flag_A ( syn_flag_A),
|
|
||||||
.syn_flag_B ( syn_flag_B),
|
|
||||||
.syn_irq_n ( syn_irq_n )
|
|
||||||
);
|
);
|
||||||
|
endmodule // jt03
|
||||||
jt12_syn u_syn(
|
|
||||||
.rst ( syn_rst ),
|
|
||||||
.clk ( syn_clk ),
|
|
||||||
.din ( syn_din ),
|
|
||||||
.addr ( syn_addr ),
|
|
||||||
.busy ( syn_busy ),
|
|
||||||
.flag_A ( syn_flag_A),
|
|
||||||
.flag_B ( syn_flag_B),
|
|
||||||
.write ( syn_write ),
|
|
||||||
.limiter_en ( syn_limiter_en),
|
|
||||||
.irq_n ( syn_irq_n ),
|
|
||||||
// Mixed sound
|
|
||||||
.snd_right ( syn_snd_right ),
|
|
||||||
.snd_left ( syn_snd_left ),
|
|
||||||
.snd_sample ( syn_snd_sample),
|
|
||||||
// Multiplexed sound
|
|
||||||
.mux_right ( syn_mux_right ),
|
|
||||||
.mux_left ( syn_mux_left ),
|
|
||||||
.mux_sample ( syn_mux_sample)
|
|
||||||
);
|
|
||||||
|
|
||||||
endmodule
|
|
43
rtl/sound/jt12/jt12.vhd
Normal file
43
rtl/sound/jt12/jt12.vhd
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
library IEEE;
|
||||||
|
use IEEE.std_logic_1164.all;
|
||||||
|
|
||||||
|
package jt12 is
|
||||||
|
|
||||||
|
component jt12
|
||||||
|
port
|
||||||
|
(
|
||||||
|
rst : in std_logic;
|
||||||
|
clk : in std_logic; -- CPU clock
|
||||||
|
cen : in std_logic := '1'; -- optional clock enable, if not needed leave as '1'
|
||||||
|
din : in std_logic_vector(7 downto 0);
|
||||||
|
addr : in std_logic_vector(1 downto 0);
|
||||||
|
cs_n : in std_logic;
|
||||||
|
wr_n : in std_logic;
|
||||||
|
|
||||||
|
dout : out std_logic_vector(7 downto 0);
|
||||||
|
irq_n : out std_logic;
|
||||||
|
|
||||||
|
-- combined output
|
||||||
|
snd_right : out std_logic_vector(15 downto 0); -- signed
|
||||||
|
snd_left : out std_logic_vector(15 downto 0); -- signed
|
||||||
|
snd_sample : out std_logic
|
||||||
|
);
|
||||||
|
end component;
|
||||||
|
|
||||||
|
component jt12_genmix
|
||||||
|
port
|
||||||
|
(
|
||||||
|
rst : in std_logic;
|
||||||
|
clk : in std_logic; -- expects 54 MHz clock
|
||||||
|
fm_left : in std_logic_vector(15 downto 0); -- FM at 55kHz
|
||||||
|
fm_right: in std_logic_vector(15 downto 0); -- FM at 55kHz
|
||||||
|
psg_snd : in std_logic_vector(10 downto 0); -- PSG at 220kHz
|
||||||
|
fm_en : in std_logic;
|
||||||
|
psg_en : in std_logic;
|
||||||
|
-- Mixed sound at 54 MHz
|
||||||
|
snd_left : out std_logic_vector(15 downto 0);
|
||||||
|
snd_right : out std_logic_vector(15 downto 0)
|
||||||
|
);
|
||||||
|
end component;
|
||||||
|
|
||||||
|
end;
|
@ -1,6 +1,3 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of JT12.
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
@ -24,25 +21,25 @@
|
|||||||
Each channel can use the full range of the DAC as they do not
|
Each channel can use the full range of the DAC as they do not
|
||||||
get summed in the real chip.
|
get summed in the real chip.
|
||||||
|
|
||||||
|
Operator data is summed up without adding extra bits. This is
|
||||||
|
the case of real YM3438, which was used on Megadrive 2 models.
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
YM2612 had a limiter to prevent overflow
|
||||||
|
YM3438 did not
|
||||||
|
JT12 always has a limiter enabled
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_acc(
|
||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
module jt12_acc
|
|
||||||
(
|
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input signed [8:0] op_result,
|
input signed [8:0] op_result,
|
||||||
input [ 1:0] rl,
|
input [ 1:0] rl,
|
||||||
input limiter_en, // enables the limiter on
|
input zero,
|
||||||
// the accumulator to prevent overfow.
|
|
||||||
// I reckon that:
|
|
||||||
// YM2612 had a limiter
|
|
||||||
// YM3438 did not
|
|
||||||
// note that the order changes to deal
|
|
||||||
// with the operator pipeline delay
|
|
||||||
input s1_enters,
|
input s1_enters,
|
||||||
input s2_enters,
|
input s2_enters,
|
||||||
input s3_enters,
|
input s3_enters,
|
||||||
@ -50,129 +47,63 @@ module jt12_acc
|
|||||||
input ch6op,
|
input ch6op,
|
||||||
input [2:0] alg,
|
input [2:0] alg,
|
||||||
input pcm_en, // only enabled for channel 6
|
input pcm_en, // only enabled for channel 6
|
||||||
input [8:0] pcm,
|
input signed [8:0] pcm,
|
||||||
// combined output
|
// combined output
|
||||||
output reg signed [11:0] left,
|
output reg signed [11:0] left,
|
||||||
output reg signed [11:0] right,
|
output reg signed [11:0] right
|
||||||
output sample,
|
|
||||||
// multiplexed output
|
|
||||||
output reg signed [8:0] mux_left,
|
|
||||||
output reg signed [8:0] mux_right,
|
|
||||||
output reg mux_sample
|
|
||||||
);
|
);
|
||||||
|
|
||||||
reg signed [11:0] pre_left, pre_right;
|
parameter num_ch=6;
|
||||||
wire signed [8:0] total;
|
|
||||||
reg sum_en;
|
reg sum_en;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
case ( alg )
|
case ( alg )
|
||||||
default: sum_en <= s4_enters;
|
default: sum_en = s4_enters;
|
||||||
3'd4: sum_en <= s2_enters | s4_enters;
|
3'd4: sum_en = s2_enters | s4_enters;
|
||||||
3'd5,3'd6: sum_en <= ~s1_enters;
|
3'd5,3'd6: sum_en = ~s1_enters;
|
||||||
3'd7: sum_en <= 1'b1;
|
3'd7: sum_en = 1'b1;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
reg sum_all;
|
reg pcm_sum;
|
||||||
assign sample = ~sum_all;
|
|
||||||
|
|
||||||
wire [8:0] buffer;
|
always @(posedge clk) if(clk_en)
|
||||||
reg [8:0] buffer2;
|
if( zero ) pcm_sum <= 1'b1;
|
||||||
reg [8:0] buf_mux;
|
else if( ch6op ) pcm_sum <= 1'b0;
|
||||||
reg [1:0] rl2,rl3;
|
|
||||||
reg last_s1;
|
|
||||||
reg [1:0] mux_cnt;
|
|
||||||
|
|
||||||
wire signed [11:0] total_signext = { {3{total[8]}}, total };
|
wire use_pcm = ch6op && pcm_en;
|
||||||
|
wire sum_or_pcm = sum_en | use_pcm;
|
||||||
|
wire left_en = rl[1];
|
||||||
|
wire right_en= rl[0];
|
||||||
|
wire signed [8:0] pcm_data = pcm_sum ? pcm : 9'd0;
|
||||||
|
wire [8:0] acc_input = use_pcm ? pcm_data : op_result;
|
||||||
|
|
||||||
always @(posedge clk) begin : mux_dac_input
|
// Continuous output
|
||||||
buffer2 <= buffer;
|
wire signed [11:0] pre_left, pre_right;
|
||||||
rl2 <= rl;
|
jt12_single_acc #(.win(9),.wout(12)) u_left(
|
||||||
last_s1 <= s1_enters;
|
|
||||||
mux_cnt <= last_s1 && s3_enters ? 2'd01 : mux_cnt + 1'b1;
|
|
||||||
if( mux_cnt==2'b11 ) begin
|
|
||||||
if( s1_enters || s3_enters ) begin
|
|
||||||
buf_mux <= buffer2;
|
|
||||||
rl3 <= rl2;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
buf_mux <= buffer;
|
|
||||||
rl3 <= rl;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if( mux_cnt==2'd0 ) begin
|
|
||||||
mux_left <= rl3[1] ? buf_mux : 9'd0;
|
|
||||||
mux_right<= rl3[0] ? buf_mux : 9'd0;
|
|
||||||
mux_sample <= 1'b1;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
mux_sample <= 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst ) begin
|
|
||||||
sum_all <= 1'b0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if( s3_enters ) begin
|
|
||||||
sum_all <= 1'b1;
|
|
||||||
if( !sum_all ) begin
|
|
||||||
pre_right <= rl[0] ? total_signext : 12'd0;
|
|
||||||
pre_left <= rl[1] ? total_signext : 12'd0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
pre_right <= pre_right + (rl[0] ? total_signext : 12'd0);
|
|
||||||
pre_left <= pre_left + (rl[1] ? total_signext : 12'd0);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if( s2_enters ) begin
|
|
||||||
sum_all <= 1'b0;
|
|
||||||
left <= pre_left;
|
|
||||||
right <= pre_right;
|
|
||||||
`ifdef DUMPSOUND
|
|
||||||
$strobe("%d\t%d", left, right);
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reg signed [8:0] next, opsum, prev;
|
|
||||||
wire signed [9:0] opsum10 = next+total;
|
|
||||||
|
|
||||||
always @(*) begin
|
|
||||||
next <= sum_en ? op_result : 9'd0;
|
|
||||||
if( s3_enters )
|
|
||||||
opsum <= (ch6op && pcm_en) ? { ~pcm[8], pcm[7:0] } : next;
|
|
||||||
else begin
|
|
||||||
if( sum_en && !(ch6op && pcm_en) )
|
|
||||||
if( limiter_en ) begin
|
|
||||||
if( opsum10[9]==opsum10[8] )
|
|
||||||
opsum <= opsum10[8:0];
|
|
||||||
else begin
|
|
||||||
opsum <= opsum10[9] ? 9'h100 : 9'h0ff;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
// MSB is discarded according to
|
|
||||||
// YM3438 application notes
|
|
||||||
opsum <= opsum10[8:0];
|
|
||||||
end
|
|
||||||
else
|
|
||||||
opsum <= total;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
jt12_sh #(.width(9),.stages(6)) u_acc(
|
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( opsum ),
|
.clk_en ( clk_en ),
|
||||||
.drop ( total )
|
.op_result ( acc_input ),
|
||||||
|
.sum_en ( sum_or_pcm & left_en ),
|
||||||
|
.zero ( zero ),
|
||||||
|
.snd ( pre_left )
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh #(.width(9),.stages(6)) u_buffer(
|
jt12_single_acc #(.win(9),.wout(12)) u_right(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( s3_enters ? total : buffer ),
|
.clk_en ( clk_en ),
|
||||||
.drop ( buffer )
|
.op_result ( acc_input ),
|
||||||
|
.sum_en ( sum_or_pcm & right_en ),
|
||||||
|
.zero ( zero ),
|
||||||
|
.snd ( pre_right )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Output can be amplied by 8/6=1.33 to use full range
|
||||||
|
// an easy alternative is to add 1/4th and get 1.25 amplification
|
||||||
|
always @(posedge clk) if(clk_en) begin
|
||||||
|
left <= pre_left + { {2{left [11]}}, left [11:2] };
|
||||||
|
right <= pre_right + { {2{right[11]}}, right[11:2] };
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of JT12.
|
|
||||||
|
|
||||||
|
|
||||||
JT12 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.
|
|
||||||
|
|
||||||
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
|
||||||
Version: 1.0
|
|
||||||
Date: 14-2-2017
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
module jt12_clksync(
|
|
||||||
input rst,
|
|
||||||
input cpu_clk,
|
|
||||||
input syn_clk,
|
|
||||||
|
|
||||||
// CPU interface
|
|
||||||
input [7:0] cpu_din,
|
|
||||||
input [1:0] cpu_addr,
|
|
||||||
output[7:0] cpu_dout,
|
|
||||||
input cpu_cs_n,
|
|
||||||
input cpu_wr_n,
|
|
||||||
output cpu_irq_n,
|
|
||||||
input cpu_limiter_en,
|
|
||||||
|
|
||||||
// Synthesizer interface
|
|
||||||
output reg [7:0] syn_din,
|
|
||||||
output reg [1:0] syn_addr,
|
|
||||||
output reg syn_rst,
|
|
||||||
output reg syn_write,
|
|
||||||
output syn_limiter_en,
|
|
||||||
|
|
||||||
input syn_busy,
|
|
||||||
input syn_flag_A,
|
|
||||||
input syn_flag_B,
|
|
||||||
input syn_irq_n
|
|
||||||
);
|
|
||||||
|
|
||||||
// reset generation
|
|
||||||
reg rst_aux;
|
|
||||||
|
|
||||||
assign syn_limiter_en = cpu_limiter_en;
|
|
||||||
|
|
||||||
always @(negedge syn_clk or posedge rst)
|
|
||||||
if( rst ) begin
|
|
||||||
syn_rst <= 1'b1;
|
|
||||||
rst_aux <= 1'b1;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
syn_rst <= rst_aux;
|
|
||||||
rst_aux <= 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
reg cpu_busy;
|
|
||||||
wire cpu_flag_B, cpu_flag_A;
|
|
||||||
|
|
||||||
assign cpu_dout = cpu_cs_n ? 8'hFF : { cpu_busy, 5'h0, cpu_flag_B, cpu_flag_A };
|
|
||||||
|
|
||||||
wire write_raw = !cpu_cs_n && !cpu_wr_n;
|
|
||||||
|
|
||||||
reg [1:0]busy_sh;
|
|
||||||
always @(posedge cpu_clk) begin
|
|
||||||
busy_sh <= { busy_sh[0], syn_busy };
|
|
||||||
end
|
|
||||||
|
|
||||||
jt12_sh #(.width(3),.stages(2) ) u_syn2cpu(
|
|
||||||
.clk ( cpu_clk ),
|
|
||||||
.din ( { syn_flag_B, syn_flag_A, syn_irq_n } ),
|
|
||||||
.drop ( { cpu_flag_B, cpu_flag_A, cpu_irq_n } )
|
|
||||||
);
|
|
||||||
|
|
||||||
always @(posedge cpu_clk) begin
|
|
||||||
reg old_write;
|
|
||||||
|
|
||||||
old_write <= write_raw;
|
|
||||||
|
|
||||||
if( rst ) begin
|
|
||||||
cpu_busy <= 1'b0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if( ~old_write & write_raw ) begin
|
|
||||||
cpu_busy <= 1;
|
|
||||||
syn_write <= ~syn_write;
|
|
||||||
syn_addr <= cpu_addr;
|
|
||||||
syn_din <= cpu_din;
|
|
||||||
end
|
|
||||||
|
|
||||||
if(cpu_busy && busy_sh==2'b10) cpu_busy <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
82
rtl/sound/jt12/jt12_csr.v
Normal file
82
rtl/sound/jt12/jt12_csr.v
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 14-2-2017
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_csr( // Circular Shift Register + input mux
|
||||||
|
input rst,
|
||||||
|
input clk,
|
||||||
|
input clk_en,
|
||||||
|
input [ 7:0] din,
|
||||||
|
input [43:0] shift_in,
|
||||||
|
output [43:0] shift_out,
|
||||||
|
|
||||||
|
input up_tl,
|
||||||
|
input up_dt1,
|
||||||
|
input up_ks_ar,
|
||||||
|
input up_amen_dr,
|
||||||
|
input up_sr,
|
||||||
|
input up_sl_rr,
|
||||||
|
input up_ssgeg,
|
||||||
|
input update_op_I,
|
||||||
|
input update_op_II,
|
||||||
|
input update_op_IV
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam regop_width=44;
|
||||||
|
|
||||||
|
reg [regop_width-1:0] regop_in;
|
||||||
|
|
||||||
|
jt12_sh_rst #(.width(regop_width),.stages(12)) u_regch(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.din ( regop_in ),
|
||||||
|
.drop ( shift_out )
|
||||||
|
);
|
||||||
|
|
||||||
|
wire up_tl_op = up_tl & update_op_IV;
|
||||||
|
wire up_dt1_op = up_dt1 & update_op_I;
|
||||||
|
wire up_mul_op = up_dt1 & update_op_II;
|
||||||
|
wire up_ks_op = up_ks_ar & update_op_II;
|
||||||
|
wire up_ar_op = up_ks_ar & update_op_I;
|
||||||
|
wire up_amen_op = up_amen_dr& update_op_IV;
|
||||||
|
wire up_dr_op = up_amen_dr& update_op_I;
|
||||||
|
wire up_sr_op = up_sr & update_op_I;
|
||||||
|
wire up_sl_op = up_sl_rr & update_op_I;
|
||||||
|
wire up_rr_op = up_sl_rr & update_op_I;
|
||||||
|
wire up_ssg_op = up_ssgeg & update_op_I;
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
regop_in = {
|
||||||
|
up_tl_op ? din[6:0] : shift_in[43:37], // 7
|
||||||
|
up_dt1_op ? din[6:4] : shift_in[36:34], // 3
|
||||||
|
up_mul_op ? din[3:0] : shift_in[33:30], // 4
|
||||||
|
up_ks_op ? din[7:6] : shift_in[29:28], // 2
|
||||||
|
up_ar_op ? din[4:0] : shift_in[27:23], // 5
|
||||||
|
up_amen_op ? din[7] : shift_in[ 22], // 1
|
||||||
|
up_dr_op ? din[4:0] : shift_in[21:17], // 5
|
||||||
|
up_sr_op ? din[4:0] : shift_in[16:12], // 5
|
||||||
|
up_sl_op ? din[7:4] : shift_in[11: 8], // 4
|
||||||
|
up_rr_op ? din[3:0] : shift_in[ 7: 4], // 4
|
||||||
|
up_ssg_op ? din[3:0] : shift_in[ 3: 0] // 4
|
||||||
|
};
|
||||||
|
|
||||||
|
endmodule // jt12_reg
|
82
rtl/sound/jt12/jt12_div.v
Normal file
82
rtl/sound/jt12/jt12_div.v
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 14-2-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
module jt12_div(
|
||||||
|
input rst,
|
||||||
|
input clk,
|
||||||
|
input cen,
|
||||||
|
input [1:0] div_setting,
|
||||||
|
output reg clk_en,
|
||||||
|
output reg clk_en_ssg
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter use_ssg=0, num_ch;
|
||||||
|
|
||||||
|
reg [3:0] opn_pres, opn_cnt;
|
||||||
|
reg [2:0] ssg_pres, ssg_cnt;
|
||||||
|
reg cen_int, cen_ssg_int;
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
if( num_ch==6 ) begin
|
||||||
|
opn_pres = 4'd5;
|
||||||
|
ssg_pres = 3'd3; // unused, really
|
||||||
|
end
|
||||||
|
else
|
||||||
|
casez( div_setting )
|
||||||
|
2'b0?: { opn_pres, ssg_pres } = { 4'd2-4'd1, 3'd0 }; // 2
|
||||||
|
2'b10: { opn_pres, ssg_pres } = { 4'd6-4'd1, 3'd3 }; // 6 - Default for YM2608
|
||||||
|
2'b11: { opn_pres, ssg_pres } = { 4'd3-4'd1, 3'd1 }; // 3 - Default for YM2203
|
||||||
|
endcase // div_setting
|
||||||
|
|
||||||
|
|
||||||
|
always @(negedge clk) begin
|
||||||
|
cen_int <= opn_cnt == 4'd0;
|
||||||
|
cen_ssg_int <= ssg_cnt == 3'd0;
|
||||||
|
`ifdef FASTDIV
|
||||||
|
// always enabled for fast sims (use with GYM output, timer will not work well)
|
||||||
|
clk_en <= 1'b1;
|
||||||
|
clk_en_ssg <= 1'b1;
|
||||||
|
`else
|
||||||
|
clk_en <= cen & cen_int;
|
||||||
|
clk_en_ssg <= use_ssg ? (cen & cen_ssg_int) : 1'b0;
|
||||||
|
`endif
|
||||||
|
end
|
||||||
|
|
||||||
|
// OPN
|
||||||
|
always @(posedge clk)
|
||||||
|
if( cen ) begin
|
||||||
|
if( opn_cnt == opn_pres ) begin
|
||||||
|
opn_cnt <= 4'd0;
|
||||||
|
end
|
||||||
|
else opn_cnt <= opn_cnt + 4'd1;
|
||||||
|
end
|
||||||
|
|
||||||
|
// SSG
|
||||||
|
always @(posedge clk)
|
||||||
|
if( cen ) begin
|
||||||
|
if( ssg_cnt == ssg_pres ) begin
|
||||||
|
ssg_cnt <= 3'd0;
|
||||||
|
end
|
||||||
|
else ssg_cnt <= ssg_cnt + 3'd1;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // jt12_div
|
@ -15,607 +15,189 @@
|
|||||||
|
|
||||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
Version: 1.0
|
Version: 1.0
|
||||||
Date: 14-2-2017
|
Date: 29-10-2018
|
||||||
|
|
||||||
The non SSG-EG section is basically that of JT51's jt51_envelope.v
|
|
||||||
adapted to 6 channels, instead of the eight.
|
|
||||||
|
|
||||||
The SSG-EG is based on the works of Nemesis, published on
|
|
||||||
http://gendev.spritesmind.net/forum/search.php?st=0&sk=t&sd=d&sr=posts&keywords=SSG-EG&t=386&sf=msgonly&ch=-1&start=15
|
|
||||||
|
|
||||||
This module tries to replicate exactly the original YM2612 waveforms.
|
|
||||||
Nonetheless, the verilog code is not a replica of the original circuit
|
|
||||||
as there is no reverse engineering description of it.
|
|
||||||
|
|
||||||
Questions:
|
|
||||||
-I latch the SSG enable bit on keyon. I have to do this in order to ignore the inversion bit before the keyon
|
|
||||||
-If SSG enable is set to 0 by software before issueing a keyoff it will be ignored
|
|
||||||
-However, the other SSG bits will have an effect if changed in the meantime between keyon and keyoff
|
|
||||||
-Was YM2612 like that?
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
tab size 4
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module jt12_eg (
|
module jt12_eg (
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
input test_eg,
|
|
||||||
`endif
|
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input zero,
|
input zero,
|
||||||
input eg_stop,
|
input eg_stop,
|
||||||
// envelope configuration
|
// envelope configuration
|
||||||
input [4:0] keycode_III,
|
input [4:0] keycode_II,
|
||||||
input [4:0] arate_II, // attack rate
|
input [4:0] arate_I, // attack rate
|
||||||
input [4:0] rate1_II, // decay rate
|
input [4:0] rate1_I, // decay rate
|
||||||
input [4:0] rate2_II, // sustain rate
|
input [4:0] rate2_I, // sustain rate
|
||||||
input [3:0] rrate_II, // release rate
|
input [3:0] rrate_I, // release rate
|
||||||
input [3:0] d1l, // sustain level
|
input [3:0] sl_I, // sustain level
|
||||||
input [1:0] ks_III, // key scale
|
input [1:0] ks_II, // key scale
|
||||||
// SSG operation
|
// SSG operation
|
||||||
input ssg_en_II,
|
input ssg_en_I,
|
||||||
input [2:0] ssg_eg_II,
|
input [2:0] ssg_eg_I,
|
||||||
// envelope operation
|
// envelope operation
|
||||||
input keyon_II,
|
input keyon_I,
|
||||||
// envelope number
|
// envelope number
|
||||||
input [6:0] am,
|
input [6:0] lfo_mod,
|
||||||
input [6:0] tl_VII,
|
input amsen_IV,
|
||||||
input [1:0] ams_VII,
|
input [1:0] ams_IV,
|
||||||
input amsen_VII,
|
input [6:0] tl_IV,
|
||||||
|
|
||||||
output reg [9:0] eg_IX,
|
output reg [9:0] eg_V,
|
||||||
output reg pg_rst_III
|
output reg pg_rst_II
|
||||||
);
|
);
|
||||||
|
|
||||||
// eg[9:6] -> direct attenuation (divide by 2)
|
parameter num_ch=6;
|
||||||
// eg[5:0] -> mantisa attenuation (uses LUT)
|
|
||||||
// 1 LSB of eg is -0.09257 dB
|
|
||||||
|
|
||||||
wire ssg_inv_II = ssg_eg_II[2] & ssg_en_II;
|
wire [14:0] eg_cnt;
|
||||||
wire ssg_alt_II = ssg_eg_II[1] & ssg_en_II;
|
|
||||||
wire ssg_hold_II = ssg_eg_II[0] & ssg_en_II;
|
|
||||||
|
|
||||||
parameter ATTACK=3'd0, DECAY1=3'd1, DECAY2=3'd2, RELEASE=3'd7, HOLD=3'd3;
|
jt12_eg_cnt u_egcnt(
|
||||||
|
.rst ( rst ),
|
||||||
reg [4:0] d1level_II;
|
|
||||||
reg [9:0] eg_III, eg_IV, eg_V;
|
|
||||||
wire [9:0] eg_II;
|
|
||||||
|
|
||||||
reg step_V;
|
|
||||||
reg sum_up;
|
|
||||||
reg [5:0] rate_V;
|
|
||||||
|
|
||||||
// remember: { log_msb, pow_addr } <= log_val[11:0] + { tl, 5'd0 } + { eg, 2'd0 };
|
|
||||||
|
|
||||||
reg [1:0] eg_cnt_base;
|
|
||||||
reg [14:0] eg_cnt;
|
|
||||||
|
|
||||||
always @(posedge clk) begin : envelope_counter
|
|
||||||
if( rst ) begin
|
|
||||||
eg_cnt_base <= 2'd0;
|
|
||||||
eg_cnt <=15'd0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if( zero ) begin
|
|
||||||
// envelope counter increases every 3 output samples,
|
|
||||||
// there is one sample every 32 clock ticks
|
|
||||||
if( eg_cnt_base == 2'd2 ) begin
|
|
||||||
eg_cnt <= eg_cnt + 1'b1;
|
|
||||||
eg_cnt_base <= 2'd0;
|
|
||||||
end
|
|
||||||
else eg_cnt_base <= eg_cnt_base + 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
wire cnt_out; // = all_cnt_last[3*31-1:3*30];
|
|
||||||
|
|
||||||
|
|
||||||
reg [7:0] step_idx;
|
|
||||||
reg [2:0] state_III, state_IV, state_V, state_VI, state_VII, state_VIII;
|
|
||||||
wire [2:0] state_II;
|
|
||||||
|
|
||||||
|
|
||||||
wire ar_off_VI;
|
|
||||||
reg ar_off_III;
|
|
||||||
|
|
||||||
// Register Cycle I
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( d1l == 4'd15 )
|
|
||||||
d1level_II <= 5'h1f; // 93dB
|
|
||||||
else
|
|
||||||
d1level_II <= d1l;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Register Cycle II
|
|
||||||
wire ssg_invertion_II, ssg_invertion_VIII;
|
|
||||||
reg ssg_invertion_III;
|
|
||||||
reg [4:0] cfg_III;
|
|
||||||
wire ssg_pg_rst = eg_II>=10'h200 && ssg_en_II &&
|
|
||||||
!( ssg_alt_II || ssg_hold_II );
|
|
||||||
wire ssg_en_out;
|
|
||||||
wire keyon_last_II;
|
|
||||||
reg ssg_en_in_II;
|
|
||||||
|
|
||||||
always @(*) begin
|
|
||||||
if( state_II==RELEASE )
|
|
||||||
ssg_en_in_II <= 1'b0;
|
|
||||||
else
|
|
||||||
ssg_en_in_II <= keyon_II ? ssg_en_II : ssg_en_out;
|
|
||||||
end
|
|
||||||
|
|
||||||
wire ar_off_II = arate_II == 5'h1f;
|
|
||||||
|
|
||||||
wire keyon_now_II = !keyon_last_II && keyon_II;
|
|
||||||
wire keyoff_now_II = keyon_last_II && !keyon_II;
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
// ar_off_III <= arate_II == 5'h1f;
|
|
||||||
// trigger release
|
|
||||||
if( keyoff_now_II ) begin
|
|
||||||
cfg_III <= { rrate_II, 1'b1 };
|
|
||||||
state_III <= RELEASE;
|
|
||||||
pg_rst_III <= 1'b0;
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
// trigger 1st decay
|
|
||||||
if( keyon_now_II ) begin
|
|
||||||
cfg_III <= arate_II;
|
|
||||||
state_III <= ATTACK;
|
|
||||||
pg_rst_III <= 1'b1;
|
|
||||||
ar_off_III <= ar_off_II;
|
|
||||||
end
|
|
||||||
else begin : sel_rate
|
|
||||||
pg_rst_III <= (eg_II==10'h3FF) ||ssg_pg_rst;
|
|
||||||
if( (state_II==DECAY1 ||state_II==DECAY2) && ssg_en_II && eg_II >= 10'h200 ) begin
|
|
||||||
ssg_invertion_III <= ssg_alt_II ^ ssg_invertion_II;
|
|
||||||
if( ssg_hold_II ) begin
|
|
||||||
cfg_III <= 5'd0;
|
|
||||||
state_III <= HOLD; // repeats!
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
cfg_III <= rate2_II;
|
|
||||||
state_III <= ATTACK; // repeats!
|
|
||||||
ar_off_III <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
ssg_invertion_III <= state_II==RELEASE ? 1'b0 : ssg_invertion_II;
|
|
||||||
case ( state_II )
|
|
||||||
ATTACK: begin
|
|
||||||
if( eg_II==10'd0 ) begin
|
|
||||||
state_III <= DECAY1;
|
|
||||||
cfg_III <= rate1_II;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
state_III <= state_II; // attack
|
|
||||||
cfg_III <= arate_II;
|
|
||||||
end
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
DECAY1: begin
|
|
||||||
if( eg_II[9:5] >= d1level_II ) begin
|
|
||||||
cfg_III <= rate2_II;
|
|
||||||
state_III <= DECAY2;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
cfg_III <= rate1_II;
|
|
||||||
state_III <= state_II; // decay1
|
|
||||||
end
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
DECAY2:
|
|
||||||
begin
|
|
||||||
cfg_III <= rate2_II;
|
|
||||||
state_III <= state_II; // decay2
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
RELEASE: begin
|
|
||||||
cfg_III <= { rrate_II, 1'b1 };
|
|
||||||
state_III <= state_II; // release
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
HOLD: begin
|
|
||||||
cfg_III <= 5'd0;
|
|
||||||
state_III <= HOLD; // repeats!
|
|
||||||
ar_off_III <= 1'b0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
eg_III <= eg_II;
|
|
||||||
end
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////
|
|
||||||
// Register Cycle III
|
|
||||||
reg [6:0] pre_rate_III;
|
|
||||||
reg [5:0] rate_IV;
|
|
||||||
|
|
||||||
always @(*) begin : pre_rate_calc
|
|
||||||
if( cfg_III == 5'd0 )
|
|
||||||
pre_rate_III <= 6'd0;
|
|
||||||
else
|
|
||||||
case( ks_III )
|
|
||||||
2'd3: pre_rate_III <= { cfg_III, 1'b0 } + keycode_III;
|
|
||||||
2'd2: pre_rate_III <= { cfg_III, 1'b0 } + { 1'b0, keycode_III[4:1] };
|
|
||||||
2'd1: pre_rate_III <= { cfg_III, 1'b0 } + { 2'b0, keycode_III[4:2] };
|
|
||||||
2'd0: pre_rate_III <= { cfg_III, 1'b0 } + { 3'b0, keycode_III[4:3] };
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst ) begin
|
|
||||||
state_IV <= RELEASE;
|
|
||||||
eg_IV <= 10'h3ff;
|
|
||||||
rate_IV <= 5'h1F;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
state_IV <= state_III;
|
|
||||||
eg_IV <= eg_III;
|
|
||||||
rate_IV <= pre_rate_III[6] ? 6'd63 : pre_rate_III[5:0];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
///////////////////////////////////////////////////////////////////
|
|
||||||
// Register Cycle IV
|
|
||||||
reg [2:0] cnt_V;
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst ) begin
|
|
||||||
state_V <= RELEASE;
|
|
||||||
rate_V <= 5'h1f;
|
|
||||||
eg_V <= 10'h3ff;
|
|
||||||
//cnt_V<= 3'd0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
state_V <= state_IV;
|
|
||||||
rate_V <= rate_IV;
|
|
||||||
eg_V <= eg_IV;
|
|
||||||
if( state_IV == ATTACK )
|
|
||||||
case( rate_IV[5:2] )
|
|
||||||
4'h0: cnt_V <= eg_cnt[13:11];
|
|
||||||
4'h1: cnt_V <= eg_cnt[12:10];
|
|
||||||
4'h2: cnt_V <= eg_cnt[11: 9];
|
|
||||||
4'h3: cnt_V <= eg_cnt[10: 8];
|
|
||||||
4'h4: cnt_V <= eg_cnt[ 9: 7];
|
|
||||||
4'h5: cnt_V <= eg_cnt[ 8: 6];
|
|
||||||
4'h6: cnt_V <= eg_cnt[ 7: 5];
|
|
||||||
4'h7: cnt_V <= eg_cnt[ 6: 4];
|
|
||||||
4'h8: cnt_V <= eg_cnt[ 5: 3];
|
|
||||||
4'h9: cnt_V <= eg_cnt[ 4: 2];
|
|
||||||
4'ha: cnt_V <= eg_cnt[ 3: 1];
|
|
||||||
default: cnt_V <= eg_cnt[ 2: 0];
|
|
||||||
endcase
|
|
||||||
else
|
|
||||||
case( rate_IV[5:2] )
|
|
||||||
4'h0: cnt_V <= eg_cnt[14:12];
|
|
||||||
4'h1: cnt_V <= eg_cnt[13:11];
|
|
||||||
4'h2: cnt_V <= eg_cnt[12:10];
|
|
||||||
4'h3: cnt_V <= eg_cnt[11: 9];
|
|
||||||
4'h4: cnt_V <= eg_cnt[10: 8];
|
|
||||||
4'h5: cnt_V <= eg_cnt[ 9: 7];
|
|
||||||
4'h6: cnt_V <= eg_cnt[ 8: 6];
|
|
||||||
4'h7: cnt_V <= eg_cnt[ 7: 5];
|
|
||||||
4'h8: cnt_V <= eg_cnt[ 6: 4];
|
|
||||||
4'h9: cnt_V <= eg_cnt[ 5: 3];
|
|
||||||
4'ha: cnt_V <= eg_cnt[ 4: 2];
|
|
||||||
4'hb: cnt_V <= eg_cnt[ 3: 1];
|
|
||||||
default: cnt_V <= eg_cnt[ 2: 0];
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// Register Cycle V
|
|
||||||
always @(*) begin : rate_step
|
|
||||||
if( rate_V[5:4]==2'b11 ) begin // 0 means 1x, 1 means 2x
|
|
||||||
if( rate_V[5:2]==4'hf && state_V == ATTACK)
|
|
||||||
step_idx <= 8'b11111111; // Maximum attack speed, rates 60&61
|
|
||||||
else
|
|
||||||
case( rate_V[1:0] )
|
|
||||||
2'd0: step_idx <= 8'b00000000;
|
|
||||||
2'd1: step_idx <= 8'b10001000; // 2
|
|
||||||
2'd2: step_idx <= 8'b10101010; // 4
|
|
||||||
2'd3: step_idx <= 8'b11101110; // 6
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if( rate_V[5:2]==4'd0 && state_V != ATTACK)
|
|
||||||
step_idx <= 8'b11111110; // limit slowest decay rate_IV
|
|
||||||
else
|
|
||||||
case( rate_V[1:0] )
|
|
||||||
2'd0: step_idx <= 8'b10101010; // 4
|
|
||||||
2'd1: step_idx <= 8'b11101010; // 5
|
|
||||||
2'd2: step_idx <= 8'b11101110; // 6
|
|
||||||
2'd3: step_idx <= 8'b11111110; // 7
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
// a rate_IV of zero keeps the level still
|
|
||||||
step_V <= rate_V[5:1]==5'd0 ? 1'b0 : step_idx[ cnt_V ];
|
|
||||||
end
|
|
||||||
|
|
||||||
reg [5:1] rate_VI;
|
|
||||||
reg [9:0] eg_VI;
|
|
||||||
reg step_VI;
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst ) begin
|
|
||||||
state_VI <= RELEASE;
|
|
||||||
rate_VI <= 5'd1;
|
|
||||||
eg_VI <= 10'h3ff;
|
|
||||||
sum_up <= 1'b0;
|
|
||||||
step_VI <= 1'b0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
state_VI <= state_V;
|
|
||||||
rate_VI <= rate_V[5:1];
|
|
||||||
eg_VI <= eg_V;
|
|
||||||
sum_up <= cnt_V[0] != cnt_out;
|
|
||||||
step_VI <= step_V;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// Register cycle VI
|
|
||||||
reg [3:0] preatt_VI;
|
|
||||||
reg [5:0] att_VI;
|
|
||||||
wire ssg_en_VI;
|
|
||||||
reg [9:0] eg_VII, eg_stopped_VII;
|
|
||||||
reg [10:0] egatt_VI;
|
|
||||||
|
|
||||||
always @(*) begin
|
|
||||||
case( rate_VI[5:2] )
|
|
||||||
4'b1100: preatt_VI <= { step_VI, ~step_VI }; // 12
|
|
||||||
4'b1101: preatt_VI <= { step_VI, ~step_VI, 1'b0 }; // 13
|
|
||||||
4'b1110: preatt_VI <= { step_VI, ~step_VI, 2'b0 }; // 14
|
|
||||||
4'b1111: preatt_VI <= 4'd8;// 15
|
|
||||||
default: preatt_VI <= { step_VI, 1'b0 };
|
|
||||||
endcase
|
|
||||||
att_VI <= ssg_en_VI ? { preatt_VI, 2'd0 } : { 2'd0, preatt_VI };
|
|
||||||
egatt_VI <= att_VI + eg_VI;
|
|
||||||
eg_stopped_VII <= eg_VI;
|
|
||||||
end
|
|
||||||
|
|
||||||
reg [8:0] ar_sum0;
|
|
||||||
reg [9:0] ar_result, ar_sum;
|
|
||||||
|
|
||||||
always @(*) begin : ar_calculation
|
|
||||||
casex( rate_VI[5:2] )
|
|
||||||
default: ar_sum0 <= eg_VI[9:4] + 1'd1;
|
|
||||||
4'b1100: ar_sum0 <= eg_VI[9:4] + 1'd1;
|
|
||||||
4'b1101: ar_sum0 <= eg_VI[9:3] + 1'd1;
|
|
||||||
4'b111x: ar_sum0 <= eg_VI[9:2] + 1'd1;
|
|
||||||
endcase
|
|
||||||
if( rate_VI[5:4] == 2'b11 )
|
|
||||||
ar_sum <= step_VI ? { ar_sum0, 1'b0 } : { 1'b0, ar_sum0 };
|
|
||||||
else
|
|
||||||
ar_sum <= step_VI ? { 1'b0, ar_sum0 } : 10'd0;
|
|
||||||
ar_result <= ar_sum<eg_VI ? eg_VI-ar_sum : 10'd0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst ) begin
|
|
||||||
eg_VII <= 10'h3ff;
|
|
||||||
state_VII <= RELEASE;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if( ar_off_VI ) begin
|
|
||||||
// eg_VII <= ssg_en_II ? 10'h200 : 10'd0;
|
|
||||||
eg_VII <= 10'd0;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if( state_VI == ATTACK ) begin
|
|
||||||
if( sum_up && eg_VI != 10'd0 )
|
|
||||||
if( rate_VI[5:1]==4'hf )
|
|
||||||
eg_VII <= 10'd0;
|
|
||||||
else
|
|
||||||
eg_VII <= ar_result;
|
|
||||||
else
|
|
||||||
eg_VII <= eg_VI;
|
|
||||||
end
|
|
||||||
else begin : DECAY_SUM
|
|
||||||
if( sum_up ) begin
|
|
||||||
if ( egatt_VI<= 10'd1023 )
|
|
||||||
eg_VII <= egatt_VI[9:0];
|
|
||||||
else eg_VII <= 10'h3FF;
|
|
||||||
end
|
|
||||||
else eg_VII <= eg_VI;
|
|
||||||
end
|
|
||||||
state_VII <= state_VI;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// Register cycle VII
|
|
||||||
reg [9:0] eg_internal_VIII;
|
|
||||||
reg [8:0] am_final;
|
|
||||||
reg [11:0] sum_eg_tl;
|
|
||||||
|
|
||||||
always @(*) begin : sum_eg_and_tl
|
|
||||||
casex( {amsen_VII, ams_VII } )
|
|
||||||
3'b0xx,3'b100: am_final <= 9'd0;
|
|
||||||
3'b101: am_final <= { 2'b00, am };
|
|
||||||
3'b110: am_final <= { 1'b0, am, 1'b0};
|
|
||||||
3'b111: am_final <= { am, 2'b0 };
|
|
||||||
endcase
|
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
if( test_eg && tl_VII!=7'd0 )
|
|
||||||
sum_eg_tl <= 11'd0;
|
|
||||||
else
|
|
||||||
`endif
|
|
||||||
sum_eg_tl <= { tl_VII, 3'd0 }
|
|
||||||
+ eg_VII
|
|
||||||
+ { am_final, 1'b0 };
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst ) begin
|
|
||||||
eg_internal_VIII <= 10'h3ff;
|
|
||||||
state_VIII <= RELEASE;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
eg_internal_VIII <= sum_eg_tl[11:10] > 2'b0 ? {10{1'b1}} : sum_eg_tl[9:0];
|
|
||||||
state_VIII <= state_VII;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// Register cycle VIII
|
|
||||||
wire ssg_inv_VIII, ssg_en_VIII;
|
|
||||||
//reg [9:0] eg_IX;
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if( rst )
|
|
||||||
eg_IX <= 10'h3ff;
|
|
||||||
else begin
|
|
||||||
if( ssg_en_VIII && (ssg_invertion_VIII ^^ ssg_inv_VIII) )
|
|
||||||
eg_IX <= eg_internal_VIII>=10'h200 ? 10'h0 : (10'h200 - eg_internal_VIII);
|
|
||||||
else
|
|
||||||
eg_IX <= eg_internal_VIII;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// Register cycle IX-XII
|
|
||||||
/*
|
|
||||||
jt12_sh #(.width(10), .stages(12-8)) u_padding(
|
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( eg_IX ),
|
.clk_en ( clk_en & ~eg_stop ),
|
||||||
.drop ( eg_XII )
|
.zero ( zero ),
|
||||||
|
.eg_cnt ( eg_cnt)
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
// Shift registers
|
|
||||||
|
|
||||||
jt12_sh24 #( .width(1) ) u_ssgen(
|
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 ssg_inv_in_I, ssg_inv_out_I;
|
||||||
|
reg ssg_inv_II, ssg_inv_III, ssg_inv_IV;
|
||||||
|
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, ssg_en_II, ssg_en_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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
jt12_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
|
||||||
|
.arate ( arate_I ), // attack rate
|
||||||
|
.rate1 ( rate1_I ), // decay rate
|
||||||
|
.rate2 ( rate2_I ), // sustain rate
|
||||||
|
.rrate ( rrate_I ),
|
||||||
|
.sl ( sl_I ), // sustain level
|
||||||
|
// SSG operation
|
||||||
|
.ssg_en ( ssg_en_I ),
|
||||||
|
.ssg_eg ( ssg_eg_I ),
|
||||||
|
// SSG output inversion
|
||||||
|
.ssg_inv_in ( ssg_inv_in_I ),
|
||||||
|
.ssg_inv_out ( ssg_inv_out_I ),
|
||||||
|
|
||||||
|
.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 ),
|
||||||
|
.ks ( ks_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_ssg_en ( ssg_en_III ),
|
||||||
|
.pure_eg_in ( eg_in_III ),
|
||||||
|
.pure_eg_out ( pure_eg_out_III ),
|
||||||
|
.sum_up_in ( sum_in_III ),
|
||||||
|
///////////////////////////////////
|
||||||
|
// IV
|
||||||
|
.lfo_mod ( lfo_mod ),
|
||||||
|
.amsen ( amsen_IV ),
|
||||||
|
.ams ( ams_IV ),
|
||||||
|
.tl ( tl_IV ),
|
||||||
|
.final_ssg_inv ( ssg_inv_IV ),
|
||||||
|
.final_eg_in ( eg_in_IV ),
|
||||||
|
.final_eg_out ( eg_out_IV )
|
||||||
|
);
|
||||||
|
|
||||||
|
always @(posedge clk) if(clk_en) begin
|
||||||
|
eg_in_II <= eg_in_I;
|
||||||
|
attack_II <= state_next_I[0];
|
||||||
|
base_rate_II<= base_rate_I;
|
||||||
|
ssg_en_II <= ssg_en_I;
|
||||||
|
ssg_inv_II <= ssg_inv_out_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];
|
||||||
|
ssg_en_III <= ssg_en_II;
|
||||||
|
ssg_inv_III <= ssg_inv_II;
|
||||||
|
step_III <= step_II;
|
||||||
|
sum_in_III <= sum_out_II;
|
||||||
|
|
||||||
|
ssg_inv_IV <= ssg_inv_III;
|
||||||
|
eg_in_IV <= pure_eg_out_III;
|
||||||
|
eg_V <= eg_out_IV;
|
||||||
|
end
|
||||||
|
|
||||||
|
jt12_sh #( .width(1), .stages(4*num_ch) ) u_cntsh(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( ssg_en_in_II ),
|
.clk_en ( clk_en ),
|
||||||
.st4 ( ssg_en_VI ),
|
.din ( cnt_lsb_II),
|
||||||
.st6 ( ssg_en_VIII ), // note that din is *_II
|
.drop ( cnt_in_II )
|
||||||
.st24 ( ssg_en_out )
|
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh #( .width(1), .stages(6) ) u_ssgattsh(
|
jt12_sh_rst #( .width(10), .stages(4*num_ch-3), .rstval(1'b1) ) u_egsh(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( ssg_inv_II ),
|
.clk_en ( clk_en ),
|
||||||
.drop ( ssg_inv_VIII )
|
.rst ( rst ),
|
||||||
|
.din ( eg_in_IV ),
|
||||||
|
.drop ( eg_in_I )
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh #( .width(1), .stages(3) ) u_aroffsh(
|
jt12_sh_rst #( .width(3), .stages(4*num_ch), .rstval(1'b1) ) u_egstate(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( ar_off_III),
|
.clk_en ( clk_en ),
|
||||||
.drop ( ar_off_VI )
|
.rst ( rst ),
|
||||||
|
.din ( state_next_I ),
|
||||||
|
.drop ( state_in_I )
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh #( .width(1), .stages(5) ) u_ssg1sh(
|
jt12_sh_rst #( .width(1), .stages(4*num_ch-3), .rstval(1'b0) ) u_ssg_inv(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( ssg_invertion_III ),
|
.clk_en ( clk_en ),
|
||||||
.drop ( ssg_invertion_VIII )
|
.rst ( rst ),
|
||||||
|
.din ( ssg_inv_IV ),
|
||||||
|
.drop ( ssg_inv_in_I )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jt12_sh_rst #( .width(1), .stages(4*num_ch), .rstval(1'b0) ) u_konsh(
|
||||||
jt12_sh #( .width(1), .stages(18) ) u_ssg2sh(
|
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( ssg_invertion_VIII ),
|
.clk_en ( clk_en ),
|
||||||
.drop ( ssg_invertion_II )
|
.rst ( rst ),
|
||||||
|
.din ( keyon_I ),
|
||||||
|
.drop ( keyon_last_I )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/* Had 27 stages in JT51, for 32 operators
|
endmodule // jt12_eg
|
||||||
Has 19 stages here, for 24 operators
|
|
||||||
plus 1 extra stage. 20 stages does not work well.
|
|
||||||
Maybe JT51 should be 26!! */
|
|
||||||
jt12_sh/*_rst*/ #( .width(10), .stages(19)/*, .rstval(1'b1)*/ ) u_egsh(
|
|
||||||
.clk ( clk ),
|
|
||||||
// .rst ( rst ),
|
|
||||||
.din ( eg_stop ? eg_stopped_VII : eg_VII ),
|
|
||||||
.drop ( eg_II )
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Had 32 stages in JT51, for 32 operators
|
|
||||||
Has 24 stages here, for 24 operators */
|
|
||||||
jt12_sh/*_rst*/ #( .width(1), .stages(24) ) u_cntsh(
|
|
||||||
.clk ( clk ),
|
|
||||||
// .rst ( rst ),
|
|
||||||
.din ( cnt_V[0] ),
|
|
||||||
.drop ( cnt_out )
|
|
||||||
);
|
|
||||||
|
|
||||||
jt12_sh_rst #( .width(1), .stages(24) ) u_konsh(
|
|
||||||
.clk ( clk ),
|
|
||||||
// .rst ( rst ),
|
|
||||||
.din ( keyon_II ),
|
|
||||||
.drop ( keyon_last_II )
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Had 31 stages in JT51, for 32 operators
|
|
||||||
Has 23 stages here, for 24 operators */
|
|
||||||
jt12_sh/*_rst*/ #( .width(3), .stages(18)/*, .rstval(1'b1)*/ ) u_statesh(
|
|
||||||
.clk ( clk ),
|
|
||||||
// .rst ( rst ),
|
|
||||||
.din ( state_VIII),
|
|
||||||
.drop ( state_II )
|
|
||||||
);
|
|
||||||
|
|
||||||
`ifdef SIMULATION
|
|
||||||
reg [4:0] sep24_cnt;
|
|
||||||
|
|
||||||
wire [2:0] state_ch0s1, state_ch1s1, state_ch2s1, state_ch3s1,
|
|
||||||
state_ch4s1, state_ch5s1, state_ch0s2, state_ch1s2,
|
|
||||||
state_ch2s2, state_ch3s2, state_ch4s2, state_ch5s2,
|
|
||||||
state_ch0s3, state_ch1s3, state_ch2s3, state_ch3s3,
|
|
||||||
state_ch4s3, state_ch5s3, state_ch0s4, state_ch1s4,
|
|
||||||
state_ch2s4, state_ch3s4, state_ch4s4, state_ch5s4;
|
|
||||||
|
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
|
||||||
|
|
||||||
sep24 #( .width(3), .pos0(0) ) stsep
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.mixed ( state_II ),
|
|
||||||
.mask ( 0 ),
|
|
||||||
.cnt ( sep24_cnt ),
|
|
||||||
|
|
||||||
.ch0s1 (state_ch0s1),
|
|
||||||
.ch1s1 (state_ch1s1),
|
|
||||||
.ch2s1 (state_ch2s1),
|
|
||||||
.ch3s1 (state_ch3s1),
|
|
||||||
.ch4s1 (state_ch4s1),
|
|
||||||
.ch5s1 (state_ch5s1),
|
|
||||||
|
|
||||||
.ch0s2 (state_ch0s2),
|
|
||||||
.ch1s2 (state_ch1s2),
|
|
||||||
.ch2s2 (state_ch2s2),
|
|
||||||
.ch3s2 (state_ch3s2),
|
|
||||||
.ch4s2 (state_ch4s2),
|
|
||||||
.ch5s2 (state_ch5s2),
|
|
||||||
|
|
||||||
.ch0s3 (state_ch0s3),
|
|
||||||
.ch1s3 (state_ch1s3),
|
|
||||||
.ch2s3 (state_ch2s3),
|
|
||||||
.ch3s3 (state_ch3s3),
|
|
||||||
.ch4s3 (state_ch4s3),
|
|
||||||
.ch5s3 (state_ch5s3),
|
|
||||||
|
|
||||||
.ch0s4 (state_ch0s4),
|
|
||||||
.ch1s4 (state_ch1s4),
|
|
||||||
.ch2s4 (state_ch2s4),
|
|
||||||
.ch3s4 (state_ch3s4),
|
|
||||||
.ch4s4 (state_ch4s4),
|
|
||||||
.ch5s4 (state_ch5s4)
|
|
||||||
);
|
|
||||||
|
|
||||||
`endif
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
|
|
50
rtl/sound/jt12/jt12_eg_cnt.v
Normal file
50
rtl/sound/jt12/jt12_eg_cnt.v
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 29-10-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_eg_cnt(
|
||||||
|
input rst,
|
||||||
|
input clk,
|
||||||
|
input clk_en,
|
||||||
|
input zero,
|
||||||
|
output reg [14:0] eg_cnt
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [1:0] eg_cnt_base;
|
||||||
|
|
||||||
|
always @(posedge clk) begin : envelope_counter
|
||||||
|
if( rst ) begin
|
||||||
|
eg_cnt_base <= 2'd0;
|
||||||
|
eg_cnt <=15'd0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if( zero && clk_en ) begin
|
||||||
|
// envelope counter increases every 3 output samples,
|
||||||
|
// there is one sample every 24 clock ticks
|
||||||
|
if( eg_cnt_base == 2'd2 ) begin
|
||||||
|
eg_cnt <= eg_cnt + 1'b1;
|
||||||
|
eg_cnt_base <= 2'd0;
|
||||||
|
end
|
||||||
|
else eg_cnt_base <= eg_cnt_base + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // jt12_eg_cnt
|
139
rtl/sound/jt12/jt12_eg_comb.v
Normal file
139
rtl/sound/jt12/jt12_eg_comb.v
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 30-10-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_eg_comb(
|
||||||
|
input keyon_now,
|
||||||
|
input keyoff_now,
|
||||||
|
input [2:0] state_in,
|
||||||
|
input [9:0] eg_in,
|
||||||
|
// envelope configuration
|
||||||
|
input [4:0] arate, // attack rate
|
||||||
|
input [4:0] rate1, // decay rate
|
||||||
|
input [4:0] rate2, // sustain rate
|
||||||
|
input [3:0] rrate,
|
||||||
|
input [3:0] sl, // sustain level
|
||||||
|
// SSG operation
|
||||||
|
input ssg_en,
|
||||||
|
input [2:0] ssg_eg,
|
||||||
|
// SSG output inversion
|
||||||
|
input ssg_inv_in,
|
||||||
|
output ssg_inv_out,
|
||||||
|
|
||||||
|
output [4:0] base_rate,
|
||||||
|
output [2:0] state_next,
|
||||||
|
output pg_rst,
|
||||||
|
///////////////////////////////////
|
||||||
|
// II
|
||||||
|
input step_attack,
|
||||||
|
input [ 4:0] step_rate_in,
|
||||||
|
input [ 4:0] keycode,
|
||||||
|
input [14:0] eg_cnt,
|
||||||
|
input cnt_in,
|
||||||
|
input [ 1:0] ks,
|
||||||
|
output cnt_lsb,
|
||||||
|
output step,
|
||||||
|
output [5:0] step_rate_out,
|
||||||
|
output sum_up_out,
|
||||||
|
///////////////////////////////////
|
||||||
|
// III
|
||||||
|
input pure_attack,
|
||||||
|
input pure_step,
|
||||||
|
input [ 5:1] pure_rate,
|
||||||
|
input pure_ssg_en,
|
||||||
|
input [ 9:0] pure_eg_in,
|
||||||
|
output [9:0] pure_eg_out,
|
||||||
|
input sum_up_in,
|
||||||
|
///////////////////////////////////
|
||||||
|
// IV
|
||||||
|
input [ 6:0] lfo_mod,
|
||||||
|
input amsen,
|
||||||
|
input [ 1:0] ams,
|
||||||
|
input [ 6:0] tl,
|
||||||
|
input [ 9:0] final_eg_in,
|
||||||
|
input final_ssg_inv,
|
||||||
|
output [9:0] final_eg_out
|
||||||
|
);
|
||||||
|
|
||||||
|
// I
|
||||||
|
jt12_eg_ctrl u_ctrl(
|
||||||
|
.keyon_now ( keyon_now ),
|
||||||
|
.keyoff_now ( keyoff_now ),
|
||||||
|
.state_in ( state_in ),
|
||||||
|
.eg ( eg_in ),
|
||||||
|
// envelope configuration
|
||||||
|
.arate ( arate ), // attack rate
|
||||||
|
.rate1 ( rate1 ), // decay rate
|
||||||
|
.rate2 ( rate2 ), // sustain rate
|
||||||
|
.rrate ( rrate ),
|
||||||
|
.sl ( sl ), // sustain level
|
||||||
|
// SSG operation
|
||||||
|
.ssg_en ( ssg_en ),
|
||||||
|
.ssg_eg ( ssg_eg ),
|
||||||
|
// SSG output inversion
|
||||||
|
.ssg_inv_in ( ssg_inv_in ),
|
||||||
|
.ssg_inv_out ( ssg_inv_out ),
|
||||||
|
|
||||||
|
.base_rate ( base_rate ),
|
||||||
|
.state_next ( state_next ),
|
||||||
|
.pg_rst ( pg_rst )
|
||||||
|
);
|
||||||
|
|
||||||
|
// II
|
||||||
|
|
||||||
|
jt12_eg_step u_step(
|
||||||
|
.attack ( step_attack ),
|
||||||
|
.base_rate ( step_rate_in ),
|
||||||
|
.keycode ( keycode ),
|
||||||
|
.eg_cnt ( eg_cnt ),
|
||||||
|
.cnt_in ( cnt_in ),
|
||||||
|
.ks ( ks ),
|
||||||
|
.cnt_lsb ( cnt_lsb ),
|
||||||
|
.step ( step ),
|
||||||
|
.rate ( step_rate_out ),
|
||||||
|
.sum_up ( sum_up_out )
|
||||||
|
);
|
||||||
|
|
||||||
|
// III
|
||||||
|
|
||||||
|
wire [9:0] egin, egout;
|
||||||
|
jt12_eg_pure u_pure(
|
||||||
|
.attack ( pure_attack ),
|
||||||
|
.step ( pure_step ),
|
||||||
|
.rate ( pure_rate ),
|
||||||
|
.ssg_en ( pure_ssg_en ),
|
||||||
|
.eg_in ( pure_eg_in ),
|
||||||
|
.eg_pure( pure_eg_out ),
|
||||||
|
.sum_up ( sum_up_in )
|
||||||
|
);
|
||||||
|
|
||||||
|
// IV
|
||||||
|
|
||||||
|
jt12_eg_final u_final(
|
||||||
|
.lfo_mod ( lfo_mod ),
|
||||||
|
.amsen ( amsen ),
|
||||||
|
.ams ( ams ),
|
||||||
|
.tl ( tl ),
|
||||||
|
.ssg_inv ( final_ssg_inv ),
|
||||||
|
.eg_pure_in ( final_eg_in ),
|
||||||
|
.eg_limited ( final_eg_out )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule // jt12_eg_comb
|
122
rtl/sound/jt12/jt12_eg_ctrl.v
Normal file
122
rtl/sound/jt12/jt12_eg_ctrl.v
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 29-10-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_eg_ctrl(
|
||||||
|
input keyon_now,
|
||||||
|
input keyoff_now,
|
||||||
|
input [2:0] state_in,
|
||||||
|
input [9:0] eg,
|
||||||
|
// envelope configuration
|
||||||
|
input [4:0] arate, // attack rate
|
||||||
|
input [4:0] rate1, // decay rate
|
||||||
|
input [4:0] rate2, // sustain rate
|
||||||
|
input [3:0] rrate,
|
||||||
|
input [3:0] sl, // sustain level
|
||||||
|
// SSG operation
|
||||||
|
input ssg_en,
|
||||||
|
input [2:0] ssg_eg,
|
||||||
|
// SSG output inversion
|
||||||
|
input ssg_inv_in,
|
||||||
|
output reg ssg_inv_out,
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
reg [4:0] sustain;
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
if( sl == 4'd15 )
|
||||||
|
sustain = 5'h1f; // 93dB
|
||||||
|
else
|
||||||
|
sustain = {1'b0, sl};
|
||||||
|
|
||||||
|
wire ssg_en_out;
|
||||||
|
reg ssg_en_in, ssg_pg_rst;
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
wire ssg_att = ssg_eg[2];
|
||||||
|
wire ssg_alt = ssg_eg[1];
|
||||||
|
wire ssg_hold = ssg_eg[0] & ssg_en;
|
||||||
|
|
||||||
|
reg ssg_over;
|
||||||
|
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
ssg_over = ssg_en && eg[9]; // eg >=10'h200
|
||||||
|
ssg_pg_rst = ssg_over && !( ssg_alt || ssg_hold );
|
||||||
|
pg_rst = keyon_now | ssg_pg_rst;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
casez ( { keyoff_now, keyon_now, state_in} )
|
||||||
|
5'b01_???: begin // key on
|
||||||
|
base_rate = arate;
|
||||||
|
state_next = ATTACK;
|
||||||
|
ssg_inv_out = ssg_att & ssg_en;
|
||||||
|
end
|
||||||
|
{2'b00, ATTACK}:
|
||||||
|
if( eg==10'd0 ) begin
|
||||||
|
base_rate = rate1;
|
||||||
|
state_next = DECAY;
|
||||||
|
ssg_inv_out = ssg_inv_in;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
base_rate = arate;
|
||||||
|
state_next = ATTACK;
|
||||||
|
ssg_inv_out = ssg_inv_in;
|
||||||
|
end
|
||||||
|
{2'b00, DECAY}: begin
|
||||||
|
if( ssg_over ) begin
|
||||||
|
base_rate = ssg_hold ? 5'd0 : arate;
|
||||||
|
state_next = ssg_hold ? HOLD : ATTACK;
|
||||||
|
ssg_inv_out = ssg_en & (ssg_alt ^ ssg_inv_in);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
base_rate = eg[9:5] >= sustain ? rate2 : rate1;
|
||||||
|
state_next = DECAY;
|
||||||
|
ssg_inv_out = ssg_inv_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{2'b00, HOLD}: begin
|
||||||
|
base_rate = 5'd0;
|
||||||
|
state_next = HOLD;
|
||||||
|
ssg_inv_out = ssg_inv_in;
|
||||||
|
end
|
||||||
|
default: begin // RELEASE, note that keyoff_now==1 will enter this state too
|
||||||
|
base_rate = { rrate, 1'b1 };
|
||||||
|
state_next = RELEASE; // release
|
||||||
|
ssg_inv_out = 1'b0; // this can produce a glitch in the output
|
||||||
|
// But to release from SSG cannot be done nicely while
|
||||||
|
// inverting the ouput
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
|
||||||
|
endmodule // jt12_eg_ctrl
|
57
rtl/sound/jt12/jt12_eg_final.v
Normal file
57
rtl/sound/jt12/jt12_eg_final.v
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 29-10-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_eg_final(
|
||||||
|
input [ 6:0] lfo_mod,
|
||||||
|
input amsen,
|
||||||
|
input [ 1:0] ams,
|
||||||
|
input [ 6:0] tl,
|
||||||
|
input [ 9:0] eg_pure_in,
|
||||||
|
input ssg_inv,
|
||||||
|
output reg [9:0] eg_limited
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [ 8:0] am_final;
|
||||||
|
reg [11:0] sum_eg_tl;
|
||||||
|
reg [11:0] sum_eg_tl_am;
|
||||||
|
reg [ 5:0] am_inverted;
|
||||||
|
reg [ 9:0] eg_pream;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
am_inverted = lfo_mod[6] ? ~lfo_mod[5:0] : lfo_mod[5:0];
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
casez( {amsen, ams } )
|
||||||
|
default: am_final = 9'd0;
|
||||||
|
3'b1_01: am_final = { 5'd0, am_inverted[5:2] };
|
||||||
|
3'b1_10: am_final = { 3'd0, am_inverted };
|
||||||
|
3'b1_11: am_final = { 2'd0, am_inverted, 1'b0 };
|
||||||
|
endcase
|
||||||
|
eg_pream = ssg_inv ? (10'h200-eg_pure_in) : eg_pure_in;
|
||||||
|
sum_eg_tl = { 1'b0, tl, 3'd0 } + {1'b0, eg_pream}; // leading zeros needed to compute correctly
|
||||||
|
sum_eg_tl_am = sum_eg_tl + { 3'd0, am_final };
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
eg_limited = sum_eg_tl_am[11:10]==2'd0 ? sum_eg_tl_am[9:0] : 10'h3ff;
|
||||||
|
|
||||||
|
endmodule // jt12_eg_final
|
81
rtl/sound/jt12/jt12_eg_pure.v
Normal file
81
rtl/sound/jt12/jt12_eg_pure.v
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 29-10-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_eg_pure(
|
||||||
|
input attack,
|
||||||
|
input step,
|
||||||
|
input [ 5:1] rate,
|
||||||
|
input [ 9:0] eg_in,
|
||||||
|
input ssg_en,
|
||||||
|
input 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 = ssg_en ? {4'd0, dr_sum, 2'd0} : {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 // jt12_eg_pure
|
111
rtl/sound/jt12/jt12_eg_step.v
Normal file
111
rtl/sound/jt12/jt12_eg_step.v
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 29-10-2018
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_eg_step(
|
||||||
|
input attack,
|
||||||
|
input [ 4:0] base_rate,
|
||||||
|
input [ 4:0] keycode,
|
||||||
|
input [14:0] eg_cnt,
|
||||||
|
input cnt_in,
|
||||||
|
input [ 1:0] ks,
|
||||||
|
output 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
|
||||||
|
case( ks )
|
||||||
|
2'd3: pre_rate = { base_rate, 1'b0 } + { 1'b0, keycode };
|
||||||
|
2'd2: pre_rate = { base_rate, 1'b0 } + { 2'b0, keycode[4:1] };
|
||||||
|
2'd1: pre_rate = { base_rate, 1'b0 } + { 3'b0, keycode[4:2] };
|
||||||
|
2'd0: pre_rate = { base_rate, 1'b0 } + { 4'b0, keycode[4:3] };
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
rate = pre_rate[6] ? 6'd63 : 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 @(*)
|
||||||
|
|
||||||
|
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
|
@ -24,53 +24,279 @@
|
|||||||
Date: 27-1-2017
|
Date: 27-1-2017
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// altera message_off 10030
|
// altera message_off 10030
|
||||||
|
|
||||||
module jt12_exprom
|
module jt12_exprom
|
||||||
(
|
(
|
||||||
input [4:0] addr,
|
input [7:0] addr,
|
||||||
input clk,
|
input clk,
|
||||||
output reg [44:0] exp
|
input clk_en,
|
||||||
|
output reg [9:0] exp
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [44:0] explut_jt51[31:0];
|
reg [9:0] explut_jt51[255:0];
|
||||||
initial
|
initial
|
||||||
begin
|
begin
|
||||||
explut_jt51[0] <= 45'b111110101011010110001011010000010010111011011;
|
explut_jt51[8'd000] = 10'd1018;
|
||||||
explut_jt51[1] <= 45'b111101010011010101000011001100101110110101011;
|
explut_jt51[8'd001] = 10'd1013;
|
||||||
explut_jt51[2] <= 45'b111011111011010011110111001000110010101110011;
|
explut_jt51[8'd002] = 10'd1007;
|
||||||
explut_jt51[3] <= 45'b111010100101010010101111000100110010101000011;
|
explut_jt51[8'd003] = 10'd1002;
|
||||||
explut_jt51[4] <= 45'b111001001101010001100111000000110010100001011;
|
explut_jt51[8'd004] = 10'd0996;
|
||||||
explut_jt51[5] <= 45'b110111111011010000011110111101010010011011011;
|
explut_jt51[8'd005] = 10'd0991;
|
||||||
explut_jt51[6] <= 45'b110110100011001111010110111001010010010100100;
|
explut_jt51[8'd006] = 10'd0986;
|
||||||
explut_jt51[7] <= 45'b110101001011001110001110110101110010001110011;
|
explut_jt51[8'd007] = 10'd0980;
|
||||||
explut_jt51[8] <= 45'b110011111011001101000110110001110010001000011;
|
explut_jt51[8'd008] = 10'd0975;
|
||||||
explut_jt51[9] <= 45'b110010100011001011111110101110010010000010011;
|
explut_jt51[8'd009] = 10'd0969;
|
||||||
explut_jt51[10] <= 45'b110001010011001010111010101010010001111011011;
|
explut_jt51[8'd010] = 10'd0964;
|
||||||
explut_jt51[11] <= 45'b101111111011001001110010100110110001110101011;
|
explut_jt51[8'd011] = 10'd0959;
|
||||||
explut_jt51[12] <= 45'b101110101011001000101010100011001101101111011;
|
explut_jt51[8'd012] = 10'd0953;
|
||||||
explut_jt51[13] <= 45'b101101010101000111100110011111010001101001011;
|
explut_jt51[8'd013] = 10'd0948;
|
||||||
explut_jt51[14] <= 45'b101100000011000110100010011011110001100011011;
|
explut_jt51[8'd014] = 10'd0942;
|
||||||
explut_jt51[15] <= 45'b101010110011000101011110011000010001011101011;
|
explut_jt51[8'd015] = 10'd0937;
|
||||||
explut_jt51[16] <= 45'b101001100011000100011010010100101101010111011;
|
explut_jt51[8'd016] = 10'd0932;
|
||||||
explut_jt51[17] <= 45'b101000010011000011010010010001001101010001011;
|
explut_jt51[8'd017] = 10'd0927;
|
||||||
explut_jt51[18] <= 45'b100111000011000010010010001101101101001011011;
|
explut_jt51[8'd018] = 10'd0921;
|
||||||
explut_jt51[19] <= 45'b100101110011000001001110001010001101000101011;
|
explut_jt51[8'd019] = 10'd0916;
|
||||||
explut_jt51[20] <= 45'b100100100011000000001010000110010000111111011;
|
explut_jt51[8'd020] = 10'd0911;
|
||||||
explut_jt51[21] <= 45'b100011010010111111001010000011001100111001011;
|
explut_jt51[8'd021] = 10'd0906;
|
||||||
explut_jt51[22] <= 45'b100010000010111110000101111111101100110011011;
|
explut_jt51[8'd022] = 10'd0900;
|
||||||
explut_jt51[23] <= 45'b100000110010111101000001111100001100101101011;
|
explut_jt51[8'd023] = 10'd0895;
|
||||||
explut_jt51[24] <= 45'b011111101010111100000001111000101100101000010;
|
explut_jt51[8'd024] = 10'd0890;
|
||||||
explut_jt51[25] <= 45'b011110011010111011000001110101001100100010011;
|
explut_jt51[8'd025] = 10'd0885;
|
||||||
explut_jt51[26] <= 45'b011101001010111010000001110001110000011100011;
|
explut_jt51[8'd026] = 10'd0880;
|
||||||
explut_jt51[27] <= 45'b011100000010111001000001101110010000010110011;
|
explut_jt51[8'd027] = 10'd0874;
|
||||||
explut_jt51[28] <= 45'b011010110010111000000001101011001100010001011;
|
explut_jt51[8'd028] = 10'd0869;
|
||||||
explut_jt51[29] <= 45'b011001101010110111000001100111101100001011011;
|
explut_jt51[8'd029] = 10'd0864;
|
||||||
explut_jt51[30] <= 45'b011000100000110110000001100100010000000110010;
|
explut_jt51[8'd030] = 10'd0859;
|
||||||
explut_jt51[31] <= 45'b010111010010110101000001100001001100000000011;
|
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
|
end
|
||||||
|
|
||||||
always @ (posedge clk)
|
always @ (posedge clk) if(clk_en)
|
||||||
exp <= explut_jt51[addr];
|
exp <= explut_jt51[addr];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -26,43 +26,98 @@
|
|||||||
module jt12_kon(
|
module jt12_kon(
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input [3:0] keyon_op,
|
input [3:0] keyon_op,
|
||||||
input [2:0] keyon_ch,
|
input [2:0] keyon_ch,
|
||||||
input [1:0] cur_op,
|
input [1:0] next_op,
|
||||||
input [2:0] cur_ch,
|
input [2:0] next_ch,
|
||||||
input up_keyon,
|
input up_keyon,
|
||||||
input csm,
|
input csm,
|
||||||
input flag_A,
|
// input flag_A,
|
||||||
input overflow_A,
|
input overflow_A,
|
||||||
|
|
||||||
output reg keyon_II
|
output reg keyon_I
|
||||||
);
|
);
|
||||||
|
|
||||||
//reg csm_copy;
|
parameter num_ch=6;
|
||||||
|
|
||||||
reg din;
|
reg din;
|
||||||
wire drop;
|
wire csr_out;
|
||||||
|
|
||||||
reg [3:0] cur_op_hot;
|
reg [3:0] next_op_hot;
|
||||||
|
reg [3:0] next_op6_hot;
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
keyon_II <= (csm&&cur_ch==2'd2&&overflow_A) || drop;
|
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
case( cur_op )
|
case( next_op )
|
||||||
2'd0: cur_op_hot <= 4'b0001; // S1
|
2'd0: next_op_hot = 4'b0001; // S1
|
||||||
2'd1: cur_op_hot <= 4'b0100; // S3
|
2'd1: next_op_hot = 4'b0100; // S3
|
||||||
2'd2: cur_op_hot <= 4'b0010; // S2
|
2'd2: next_op_hot = 4'b0010; // S2
|
||||||
2'd3: cur_op_hot <= 4'b1000; // S4
|
2'd3: next_op_hot = 4'b1000; // S4
|
||||||
endcase
|
endcase
|
||||||
din <= keyon_ch==cur_ch && up_keyon ? |(keyon_op&cur_op_hot) : drop;
|
din = keyon_ch==next_ch && up_keyon ? |(keyon_op&next_op_hot) : csr_out;
|
||||||
end
|
end
|
||||||
|
|
||||||
jt12_sh_rst #(.width(1),.stages(24)) u_konch(
|
generate
|
||||||
|
if(num_ch==6) begin
|
||||||
|
// capture overflow signal so it lasts long enough
|
||||||
|
reg overflow2;
|
||||||
|
reg [4:0] overflow_cycle;
|
||||||
|
|
||||||
|
always @(posedge clk) if( clk_en ) begin
|
||||||
|
if(overflow_A) begin
|
||||||
|
overflow2 <= 1'b1;
|
||||||
|
overflow_cycle <= { next_op, next_ch };
|
||||||
|
end else begin
|
||||||
|
if(overflow_cycle == {next_op, next_ch}) overflow2<=1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
wire middle;
|
||||||
|
reg mid_din;
|
||||||
|
|
||||||
|
always @(posedge clk) if( clk_en )
|
||||||
|
keyon_I <= (csm&&next_ch==3'd2&&overflow2) || csr_out;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
case( {~next_op[1], next_op[0]} )
|
||||||
|
2'd0: next_op6_hot = 4'b0001; // S1
|
||||||
|
2'd1: next_op6_hot = 4'b0100; // S3
|
||||||
|
2'd2: next_op6_hot = 4'b0010; // S2
|
||||||
|
2'd3: next_op6_hot = 4'b1000; // S4
|
||||||
|
endcase
|
||||||
|
mid_din = keyon_ch==next_ch && up_keyon ? |(keyon_op&next_op6_hot) : middle;
|
||||||
|
end
|
||||||
|
|
||||||
|
jt12_sh_rst #(.width(1),.stages(12),.rstval(1'b0)) u_konch0(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
// .rst ( rst ),
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
.din ( din ),
|
.din ( din ),
|
||||||
.drop ( drop )
|
.drop ( middle )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jt12_sh_rst #(.width(1),.stages(12),.rstval(1'b0)) u_konch1(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.din ( mid_din ),
|
||||||
|
.drop ( csr_out )
|
||||||
|
);
|
||||||
|
end
|
||||||
|
else begin // 3 channels
|
||||||
|
always @(posedge clk) if( clk_en )
|
||||||
|
keyon_I <= csr_out; // No CSM for YM2203
|
||||||
|
|
||||||
|
jt12_sh_rst #(.width(1),.stages(12),.rstval(1'b0)) u_konch1(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.din ( din ),
|
||||||
|
.drop ( csr_out )
|
||||||
|
);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -22,47 +22,82 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
tab size 4
|
Does the LFO frequency depend on the pre-scaler for YM2608 ?
|
||||||
|
|
||||||
|
From spritesmind.net:
|
||||||
|
"That would be 7-bit LFO step counter (which is incremented on each LFO clock and reset when LFO enable bit is cleared).
|
||||||
|
LFO AM value indeed corresponds to LFO step counter bits 0:5 shifted left by one
|
||||||
|
and XORed with inversion of bit 6 (to generate an inverted triangle waveform)
|
||||||
|
|
||||||
|
LFO AM sensitivity (2 bits) indicates to EG how much LFO AM value is shifted before adding to EG output
|
||||||
|
[...]
|
||||||
|
LFO PM step (0-31), which takes bits 2:6 of LFO step counter (0-127) and goes to LFO PM calcuation unit
|
||||||
|
"
|
||||||
|
|
||||||
|
From Sauraen:
|
||||||
|
|
||||||
|
The LFO seems to have 3 sections:
|
||||||
|
|
||||||
|
[*] 7-bit linear prescaler. The test bit 0x21:1 goes into what looks like the carry-in or something similar;
|
||||||
|
it could go into the reset, I can't quite tell with more detailed analysis. The 7-bit output (plus maybe carry-out)
|
||||||
|
gets logiced together into 8 lines (evidently perform "== N" with N hardcoded for each line), and these go into a
|
||||||
|
little selector unit which is also fed by the LFO Speed and LFO Enable bits. I can't quite see the output of this,
|
||||||
|
but I do see there's some sort of feedback to the prescaler's reset. So this clearly seems like a divide-by-N prescaler.
|
||||||
|
I can try to read the eight N's for you if you want, but you should be able to reverse engineer them from knowing what the LFO speeds are.
|
||||||
|
|
||||||
|
[*] 7-bit linear counter, with an 8-bit unit after the output (possibly inverts the output after each cycle to make a triangle wave?).
|
||||||
|
Bits 1:6 of the output of this go to the EG, and stick into its pipeline at the same place where the LFO->Amplitude two bits go.
|
||||||
|
(Elsewhere the operator LFO enable flag simply forces these two bits to zero for operators not affected by the LFO.)
|
||||||
|
Some modified version of the 8-bit signal between the counter and the inverter unit thing goes to the third unit of the LFO.
|
||||||
|
|
||||||
|
[*] Highly complex unit which modifies the frequency data as it goes from the channel registers to the PG. The block bits bypass this,
|
||||||
|
but all the frequency bits get modified by it. There's a bitslice portion corresponding to bits 0:6, and then what appears to be
|
||||||
|
the same logic folded over to process bits 7:A. But the interesting part is that bits 4:A of the frequency data go into the
|
||||||
|
bitslices 0:6. That is, the bitslice unit for bit 0 has bit 0 enter at the middle and leave (to the PG) at the bottom. But it also has bit 4 enter at the top.
|
||||||
|
And so on through bit 6 having bit A enter at the top. It looks like the top portion is some sort of shifter for bits 4:A--the wires go diagonally
|
||||||
|
so that bit 4 only gets used once, bit 5 gets used in bitslice 1 and 0, bit 6 gets used in bitslices 2:0, and so on so that bit A gets used in all of them.
|
||||||
|
I'm guessing this whole unit is basically a multiplier, multiplying bits 4:A of the frequency value by bits 0:7 of the LFO state, and then adding the result
|
||||||
|
to bits 0:6 of the frequency value (with carry up to the higher bits). It looks like, between the multiplied output and the adder, there's another shifter
|
||||||
|
whose value is based on the the LFO->Frequency bits. But it looks like it's a bit more complex than I'm describing.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module jt12_lfo(
|
module jt12_lfo(
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input zero,
|
input zero,
|
||||||
input lfo_rst,
|
input lfo_rst,
|
||||||
input lfo_en,
|
input lfo_en,
|
||||||
input [2:0] lfo_freq,
|
input [2:0] lfo_freq,
|
||||||
output reg [6:0] lfo_mod
|
output reg [6:0] lfo_mod // 7-bit width according to spritesmind.net
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [6:0] cnt, limit;
|
reg [6:0] cnt, limit;
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
case( lfo_freq )
|
case( lfo_freq ) // same values as in MAME
|
||||||
3'd0: limit <= 7'd108;
|
3'd0: limit = 7'd108;
|
||||||
3'd1: limit <= 7'd78;
|
3'd1: limit = 7'd77;
|
||||||
3'd2: limit <= 7'd71;
|
3'd2: limit = 7'd71;
|
||||||
3'd3: limit <= 7'd67;
|
3'd3: limit = 7'd67;
|
||||||
3'd4: limit <= 7'd62;
|
3'd4: limit = 7'd62;
|
||||||
3'd5: limit <= 7'd44;
|
3'd5: limit = 7'd44;
|
||||||
3'd6: limit <= 7'd8;
|
3'd6: limit = 7'd8;
|
||||||
3'd7: limit <= 7'd5;
|
3'd7: limit = 7'd5;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk)
|
||||||
if( rst || !lfo_en )
|
if( rst || !lfo_en )
|
||||||
{ lfo_mod, cnt } <= 14'd0;
|
{ lfo_mod, cnt } <= 14'd0;
|
||||||
else begin
|
else if( clk_en && zero) begin
|
||||||
if(zero) begin
|
|
||||||
if( cnt == limit ) begin
|
if( cnt == limit ) begin
|
||||||
cnt <= 7'd0;
|
cnt <= 7'd0;
|
||||||
lfo_mod <= lfo_mod + 1'b1;
|
lfo_mod <= lfo_mod + 1'b1;
|
||||||
end
|
end
|
||||||
else
|
else begin
|
||||||
cnt <= cnt + 1'b1;
|
cnt <= cnt + 1'b1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -30,11 +30,11 @@ module jt12_limitamp #( parameter width=20, shift=5 ) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
left_out <= ^left_in[width-1:width-1-shift] ?
|
left_out = ^left_in[width-1:width-1-shift] ?
|
||||||
{ left_in[width-1], {(width-1){~left_in[width-1]}}} :
|
{ left_in[width-1], {(width-1){~left_in[width-1]}}} :
|
||||||
left_in <<< shift;
|
left_in <<< shift;
|
||||||
|
|
||||||
right_out <= ^right_in[width-1:width-1-shift] ?
|
right_out = ^right_in[width-1:width-1-shift] ?
|
||||||
{ right_in[width-1], {(width-1){~right_in[width-1]}}} :
|
{ right_in[width-1], {(width-1){~right_in[width-1]}}} :
|
||||||
right_in <<< shift;
|
right_in <<< shift;
|
||||||
end
|
end
|
||||||
|
298
rtl/sound/jt12/jt12_logsin.v
Normal file
298
rtl/sound/jt12/jt12_logsin.v
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. 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: 27-1-2017
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
//altera message_off 10030
|
||||||
|
|
||||||
|
module jt12_logsin
|
||||||
|
(
|
||||||
|
input [7:0] addr,
|
||||||
|
input clk,
|
||||||
|
input clk_en,
|
||||||
|
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(clk_en)
|
||||||
|
logsin <= sinelut[addr];
|
||||||
|
|
||||||
|
endmodule
|
@ -23,6 +23,9 @@
|
|||||||
module jt12_mmr(
|
module jt12_mmr(
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input cen,
|
||||||
|
output clk_en,
|
||||||
|
output clk_en_ssg,
|
||||||
input [7:0] din,
|
input [7:0] din,
|
||||||
input write,
|
input write,
|
||||||
input [1:0] addr,
|
input [1:0] addr,
|
||||||
@ -46,18 +49,14 @@ module jt12_mmr(
|
|||||||
// PCM
|
// PCM
|
||||||
output reg [8:0] pcm,
|
output reg [8:0] pcm,
|
||||||
output reg pcm_en,
|
output reg pcm_en,
|
||||||
|
output reg pcm_wr, // high for one clock cycle when PCM is written
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
// Test
|
|
||||||
output reg test_eg,
|
|
||||||
output reg test_op0,
|
|
||||||
`endif
|
|
||||||
// Operator
|
// Operator
|
||||||
output use_prevprev1,
|
output xuse_prevprev1,
|
||||||
output use_internal_x,
|
output xuse_internal,
|
||||||
output use_internal_y,
|
output yuse_internal,
|
||||||
output use_prev2,
|
output xuse_prev2,
|
||||||
output use_prev1,
|
output yuse_prev1,
|
||||||
|
output yuse_prev2,
|
||||||
// PG
|
// PG
|
||||||
output [10:0] fnum_I,
|
output [10:0] fnum_I,
|
||||||
output [ 2:0] block_I,
|
output [ 2:0] block_I,
|
||||||
@ -65,26 +64,26 @@ module jt12_mmr(
|
|||||||
// REG
|
// REG
|
||||||
output [ 1:0] rl,
|
output [ 1:0] rl,
|
||||||
output [ 2:0] fb_II,
|
output [ 2:0] fb_II,
|
||||||
output [ 2:0] alg,
|
output [ 2:0] alg_I,
|
||||||
output [ 2:0] pms,
|
output [ 2:0] pms_I,
|
||||||
output [ 1:0] ams_VII,
|
output [ 1:0] ams_IV,
|
||||||
output amsen_VII,
|
output amsen_IV,
|
||||||
output [ 2:0] dt1_II,
|
output [ 2:0] dt1_I,
|
||||||
output [ 3:0] mul_V,
|
output [ 3:0] mul_II,
|
||||||
output [ 6:0] tl_VII,
|
output [ 6:0] tl_IV,
|
||||||
output reg eg_stop,
|
output reg eg_stop,
|
||||||
|
|
||||||
output [ 4:0] ar_II,
|
output [ 4:0] ar_I,
|
||||||
output [ 4:0] d1r_II,
|
output [ 4:0] d1r_I,
|
||||||
output [ 4:0] d2r_II,
|
output [ 4:0] d2r_I,
|
||||||
output [ 3:0] rr_II,
|
output [ 3:0] rr_I,
|
||||||
output [ 3:0] d1l,
|
output [ 3:0] sl_I,
|
||||||
output [ 1:0] ks_III,
|
output [ 1:0] ks_II,
|
||||||
// SSG operation
|
// SSG operation
|
||||||
output ssg_en_II,
|
output ssg_en_I,
|
||||||
output [2:0] ssg_eg_II,
|
output [2:0] ssg_eg_I,
|
||||||
|
|
||||||
output keyon_II,
|
output keyon_I,
|
||||||
|
|
||||||
// output [ 1:0] cur_op,
|
// output [ 1:0] cur_op,
|
||||||
// Operator
|
// Operator
|
||||||
@ -92,7 +91,33 @@ module jt12_mmr(
|
|||||||
output s1_enters,
|
output s1_enters,
|
||||||
output s2_enters,
|
output s2_enters,
|
||||||
output s3_enters,
|
output s3_enters,
|
||||||
output s4_enters
|
output s4_enters,
|
||||||
|
|
||||||
|
// PSG interace
|
||||||
|
output [3:0] psg_addr,
|
||||||
|
output [7:0] psg_data,
|
||||||
|
output reg psg_wr_n
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter use_ssg=0, num_ch=6, use_pcm=1;
|
||||||
|
|
||||||
|
`ifdef SIMULATION
|
||||||
|
initial begin
|
||||||
|
cen_cnt = 3'd0;
|
||||||
|
end
|
||||||
|
`include "jt12_mmr_sim.vh"
|
||||||
|
`endif
|
||||||
|
|
||||||
|
reg [1:0] div_setting;
|
||||||
|
|
||||||
|
|
||||||
|
jt12_div #(.use_ssg(use_ssg),.num_ch(num_ch)) u_div (
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.cen ( cen ),
|
||||||
|
.div_setting ( div_setting ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.clk_en_ssg ( clk_en_ssg )
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [7:0] selected_register;
|
reg [7:0] selected_register;
|
||||||
@ -102,26 +127,13 @@ reg [7:0] selected_register;
|
|||||||
reg irq_zero_en, irq_brdy_en, irq_eos_en,
|
reg irq_zero_en, irq_brdy_en, irq_eos_en,
|
||||||
irq_tb_en, irq_ta_en;
|
irq_tb_en, irq_ta_en;
|
||||||
*/
|
*/
|
||||||
reg up_clr;
|
reg [6:0] up_opreg; // hot-one encoding. tells which operator register gets updated next
|
||||||
reg up_alg;
|
reg [2:0] up_chreg; // hot-one encoding. tells which channel register gets updated next
|
||||||
|
|
||||||
reg up_block;
|
|
||||||
reg up_fnumlo;
|
|
||||||
reg up_pms;
|
|
||||||
reg up_dt1;
|
|
||||||
reg up_tl;
|
|
||||||
reg up_ks_ar;
|
|
||||||
reg up_amen_d1r;
|
|
||||||
reg up_d2r;
|
|
||||||
reg up_d1l;
|
|
||||||
reg up_ssgeg;
|
|
||||||
reg up_keyon;
|
reg up_keyon;
|
||||||
|
|
||||||
wire busy_reg;
|
wire busy_reg;
|
||||||
|
|
||||||
parameter REG_TEST = 8'h01,
|
parameter REG_TESTYM = 8'h21,
|
||||||
REG_TEST2 = 8'h02,
|
|
||||||
REG_TESTYM = 8'h21,
|
|
||||||
REG_LFO = 8'h22,
|
REG_LFO = 8'h22,
|
||||||
REG_CLKA1 = 8'h24,
|
REG_CLKA1 = 8'h24,
|
||||||
REG_CLKA2 = 8'h25,
|
REG_CLKA2 = 8'h25,
|
||||||
@ -141,29 +153,40 @@ reg csm, effect;
|
|||||||
|
|
||||||
reg [ 2:0] block_ch3op2, block_ch3op3, block_ch3op1;
|
reg [ 2:0] block_ch3op2, block_ch3op3, block_ch3op1;
|
||||||
reg [10:0] fnum_ch3op2, fnum_ch3op3, fnum_ch3op1;
|
reg [10:0] fnum_ch3op2, fnum_ch3op3, fnum_ch3op1;
|
||||||
reg [ 5:0] latch_ch3op2, latch_ch3op3, latch_ch3op1;
|
reg [ 5:0] latch_fnum;
|
||||||
|
|
||||||
|
|
||||||
reg [2:0] up_ch;
|
reg [2:0] up_ch;
|
||||||
reg [1:0] up_op;
|
reg [1:0] up_op;
|
||||||
|
|
||||||
`include "jt12_mmr_sim.vh"
|
|
||||||
|
|
||||||
always @(posedge clk) begin : memory_mapped_registers
|
|
||||||
reg old_write;
|
reg old_write;
|
||||||
|
reg [7:0] din_copy;
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
old_write <= write;
|
old_write <= write;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if( use_ssg ) begin
|
||||||
|
assign psg_addr = selected_register[3:0];
|
||||||
|
assign psg_data = din_copy;
|
||||||
|
end else begin
|
||||||
|
assign psg_addr = 4'd0;
|
||||||
|
assign psg_data = 8'd0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
reg part;
|
||||||
|
|
||||||
|
// this runs at clk speed, no clock gating here
|
||||||
|
always @(posedge clk) begin : memory_mapped_registers
|
||||||
if( rst ) begin
|
if( rst ) begin
|
||||||
selected_register <= 8'h0;
|
selected_register <= 8'h0;
|
||||||
busy <= 1'b0;
|
div_setting <= 2'b11;
|
||||||
up_ch <= 3'd0;
|
up_ch <= 3'd0;
|
||||||
up_op <= 2'd0;
|
up_op <= 2'd0;
|
||||||
{ up_keyon, up_alg, up_block, up_fnumlo,
|
up_keyon <= 1'd0;
|
||||||
up_pms, up_dt1, up_tl, up_ks_ar,
|
up_opreg <= 7'd0;
|
||||||
up_amen_d1r,up_d2r, up_d1l, up_ssgeg } <= 12'd0;
|
up_chreg <= 3'd0;
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
{ test_eg, test_op0 } <= 2'd0;
|
|
||||||
`endif
|
|
||||||
// IRQ Mask
|
// IRQ Mask
|
||||||
/*{ irq_zero_en, irq_brdy_en, irq_eos_en,
|
/*{ irq_zero_en, irq_brdy_en, irq_eos_en,
|
||||||
irq_tb_en, irq_ta_en } = 5'h1f; */
|
irq_tb_en, irq_ta_en } = 5'h1f; */
|
||||||
@ -171,7 +194,6 @@ always @(posedge clk) begin : memory_mapped_registers
|
|||||||
{ value_A, value_B } <= 18'd0;
|
{ value_A, value_B } <= 18'd0;
|
||||||
{ clr_flag_B, clr_flag_A,
|
{ clr_flag_B, clr_flag_A,
|
||||||
enable_irq_B, enable_irq_A, load_B, load_A } <= 6'd0;
|
enable_irq_B, enable_irq_A, load_B, load_A } <= 6'd0;
|
||||||
up_clr <= 1'b0;
|
|
||||||
fast_timers <= 1'b0;
|
fast_timers <= 1'b0;
|
||||||
// LFO
|
// LFO
|
||||||
lfo_freq <= 3'd0;
|
lfo_freq <= 3'd0;
|
||||||
@ -181,36 +203,32 @@ always @(posedge clk) begin : memory_mapped_registers
|
|||||||
// PCM
|
// PCM
|
||||||
pcm <= 9'h0;
|
pcm <= 9'h0;
|
||||||
pcm_en <= 1'b0;
|
pcm_en <= 1'b0;
|
||||||
|
pcm_wr <= 1'b0;
|
||||||
// sch <= 1'b0;
|
// sch <= 1'b0;
|
||||||
// Original test features
|
// Original test features
|
||||||
eg_stop <= 1'b0;
|
eg_stop <= 1'b0;
|
||||||
pg_stop <= 1'b0;
|
pg_stop <= 1'b0;
|
||||||
`ifdef SIMULATION
|
psg_wr_n <= 1'b1;
|
||||||
mmr_dump <= 1'b0;
|
|
||||||
`endif
|
|
||||||
end else begin
|
end else begin
|
||||||
// WRITE IN REGISTERS
|
// WRITE IN REGISTERS
|
||||||
if( old_write ^ write ) begin
|
if( write ) begin
|
||||||
busy <= 1'b1;
|
|
||||||
if( !addr[0] ) begin
|
if( !addr[0] ) begin
|
||||||
selected_register <= din;
|
selected_register <= din;
|
||||||
up_ch <= {addr[1], din[1:0]};
|
part <= addr[1];
|
||||||
up_op <= din[3:2]; // 0=S1,1=S3,2=S2,3=S4
|
|
||||||
end else begin
|
end else begin
|
||||||
// Global registers
|
// Global registers
|
||||||
if( selected_register < 8'h30 ) begin
|
din_copy <= din;
|
||||||
case( selected_register)
|
up_keyon <= selected_register == REG_KON;
|
||||||
// registros especiales
|
up_ch <= {part, selected_register[1:0]};
|
||||||
|
up_op <= selected_register[3:2]; // 0=S1,1=S3,2=S2,3=S4
|
||||||
|
casez( selected_register)
|
||||||
//REG_TEST: lfo_rst <= 1'b1; // regardless of din
|
//REG_TEST: lfo_rst <= 1'b1; // regardless of din
|
||||||
`ifdef TEST_SUPPORT
|
8'h0?: psg_wr_n <= 1'b0;
|
||||||
REG_TEST2: { mmr_dump, test_op0, test_eg } <= din[2:0];
|
|
||||||
`endif
|
|
||||||
REG_TESTYM: begin
|
REG_TESTYM: begin
|
||||||
eg_stop <= din[5];
|
eg_stop <= din[5];
|
||||||
pg_stop <= din[3];
|
pg_stop <= din[3];
|
||||||
fast_timers <= din[2];
|
fast_timers <= din[2];
|
||||||
end
|
end
|
||||||
REG_KON: up_keyon <= 1'b1;
|
|
||||||
REG_CLKA1: value_A[9:2]<= din;
|
REG_CLKA1: value_A[9:2]<= din;
|
||||||
REG_CLKA2: value_A[1:0]<= din[1:0];
|
REG_CLKA2: value_A[1:0]<= din[1:0];
|
||||||
REG_CLKB: value_B <= din;
|
REG_CLKB: value_B <= din;
|
||||||
@ -221,93 +239,97 @@ always @(posedge clk) begin : memory_mapped_registers
|
|||||||
enable_irq_B, enable_irq_A,
|
enable_irq_B, enable_irq_A,
|
||||||
load_B, load_A } <= din[5:0];
|
load_B, load_A } <= din[5:0];
|
||||||
end
|
end
|
||||||
|
`ifndef NOLFO
|
||||||
REG_LFO: { lfo_en, lfo_freq } <= din[3:0];
|
REG_LFO: { lfo_en, lfo_freq } <= din[3:0];
|
||||||
REG_DACTEST:pcm[0] <= din[3];
|
|
||||||
REG_PCM: pcm[8:1]<= din;
|
|
||||||
REG_PCM_EN: pcm_en <= din[7];
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
else if( selected_register[1:0]!=2'b11 ) begin
|
|
||||||
// channel registers
|
|
||||||
if( selected_register >= 8'hA0 ) begin
|
|
||||||
case( selected_register )
|
|
||||||
8'hA0, 8'hA1, 8'hA2: up_fnumlo <= 1'b1;
|
|
||||||
8'hA4, 8'hA5, 8'hA6: up_block <= 1'b1;
|
|
||||||
// CH3 special registers
|
|
||||||
8'hA9: { block_ch3op1, fnum_ch3op1 } <= { latch_ch3op1, din };
|
|
||||||
8'hA8: { block_ch3op3, fnum_ch3op3 } <= { latch_ch3op3, din };
|
|
||||||
8'hAA: { block_ch3op2, fnum_ch3op2 } <= { latch_ch3op2, din };
|
|
||||||
8'hAD: latch_ch3op1 <= din[5:0];
|
|
||||||
8'hAC: latch_ch3op3 <= din[5:0];
|
|
||||||
8'hAE: latch_ch3op2 <= din[5:0];
|
|
||||||
// FB + Algorithm
|
|
||||||
8'hB0, 8'hB1, 8'hB2: up_alg <= 1'b1;
|
|
||||||
8'hB4, 8'hB5, 8'hB6: up_pms <= 1'b1;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
else
|
|
||||||
// operator registers
|
|
||||||
begin
|
|
||||||
case( selected_register[7:4] )
|
|
||||||
4'h3: up_dt1 <= 1'b1;
|
|
||||||
4'h4: up_tl <= 1'b1;
|
|
||||||
4'h5: up_ks_ar <= 1'b1;
|
|
||||||
4'h6: up_amen_d1r <= 1'b1;
|
|
||||||
4'h7: up_d2r <= 1'b1;
|
|
||||||
4'h8: up_d1l <= 1'b1;
|
|
||||||
4'h9: up_ssgeg <= 1'b1;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else begin /* clear once-only bits */
|
|
||||||
// csm <= 1'b0;
|
|
||||||
// lfo_rst <= 1'b0;
|
|
||||||
{ clr_flag_B, clr_flag_A, load_B, load_A } <= 4'd0;
|
|
||||||
`ifdef SIMULATION
|
|
||||||
mmr_dump <= 1'b0;
|
|
||||||
`endif
|
`endif
|
||||||
up_keyon <= 1'b0;
|
// clock divider
|
||||||
if( |{ up_keyon, up_alg, up_block, up_fnumlo,
|
REG_CLK_N6: div_setting[1] <= 1'b1;
|
||||||
up_pms, up_dt1, up_tl, up_ks_ar,
|
REG_CLK_N3: div_setting[0] <= 1'b1;
|
||||||
up_amen_d1r,up_d2r, up_d1l, up_ssgeg } == 1'b0 )
|
REG_CLK_N2: div_setting <= 2'b0;
|
||||||
busy <= 0;
|
// CH3 special registers
|
||||||
|
8'hA9: { block_ch3op1, fnum_ch3op1 } <= { latch_fnum, din };
|
||||||
|
8'hA8: { block_ch3op3, fnum_ch3op3 } <= { latch_fnum, din };
|
||||||
|
8'hAA: { block_ch3op2, fnum_ch3op2 } <= { latch_fnum, din };
|
||||||
|
// According to http://www.mjsstuf.x10host.com/pages/vgmPlay/vgmPlay.htm
|
||||||
|
// There is a single fnum latch for all channels
|
||||||
|
8'hA4, 8'hA5, 8'hA6, 8'hAD, 8'hAC, 8'hAE: latch_fnum <= din[5:0];
|
||||||
|
default:; // avoid incomplete-case warning
|
||||||
|
endcase
|
||||||
|
if( use_pcm==1 ) begin // for YM2612 only
|
||||||
|
casez( selected_register)
|
||||||
|
REG_DACTEST: pcm[0] <= din[3];
|
||||||
|
REG_PCM:
|
||||||
|
pcm <= { ~din[7], din[6:0], 1'b1 };
|
||||||
|
REG_PCM_EN: pcm_en <= din[7];
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
pcm_wr <= selected_register==REG_PCM;
|
||||||
|
end
|
||||||
|
if( selected_register[1:0]==2'b11 )
|
||||||
|
{ up_chreg, up_opreg } <= { 3'h0, 7'h0 };
|
||||||
else
|
else
|
||||||
busy <= 1'b1;
|
casez( selected_register )
|
||||||
|
// channel registers
|
||||||
|
8'hA0, 8'hA1, 8'hA2: { up_chreg, up_opreg } <= { 3'h1, 7'd0 }; // up_fnumlo
|
||||||
|
// FB + Algorithm
|
||||||
|
8'hB0, 8'hB1, 8'hB2: { up_chreg, up_opreg } <= { 3'h2, 7'd0 }; // up_alg
|
||||||
|
8'hB4, 8'hB5, 8'hB6: { up_chreg, up_opreg } <= { 3'h4, 7'd0 }; // up_pms
|
||||||
|
// operator registers
|
||||||
|
8'h3?: { up_chreg, up_opreg } <= { 3'h0, 7'h01 }; // up_dt1
|
||||||
|
8'h4?: { up_chreg, up_opreg } <= { 3'h0, 7'h02 }; // up_tl
|
||||||
|
8'h5?: { up_chreg, up_opreg } <= { 3'h0, 7'h04 }; // up_ks_ar
|
||||||
|
8'h6?: { up_chreg, up_opreg } <= { 3'h0, 7'h08 }; // up_amen_dr
|
||||||
|
8'h7?: { up_chreg, up_opreg } <= { 3'h0, 7'h10 }; // up_sr
|
||||||
|
8'h8?: { up_chreg, up_opreg } <= { 3'h0, 7'h20 }; // up_sl
|
||||||
|
8'h9?: { up_chreg, up_opreg } <= { 3'h0, 7'h40 }; // up_ssgeg
|
||||||
|
default: { up_chreg, up_opreg } <= { 3'h0, 7'h0 };
|
||||||
|
endcase // selected_register
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else if(clk_en) begin /* clear once-only bits */
|
||||||
|
// lfo_rst <= 1'b0;
|
||||||
|
{ clr_flag_B, clr_flag_A } <= 2'd0;
|
||||||
|
psg_wr_n <= 1'b1;
|
||||||
|
pcm_wr <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if( busy_reg ) begin
|
reg [4:0] busy_cnt; // busy lasts for 32 synth clock cycles, like in real chip
|
||||||
up_clr <= 1'b1;
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if( rst ) begin
|
||||||
|
busy <= 1'b0;
|
||||||
|
busy_cnt <= 5'd0;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
up_clr <= 1'b0;
|
if (!old_write && write && addr[0] ) begin // only set for data writes
|
||||||
if( up_clr )
|
busy <= 1'b1;
|
||||||
{ up_alg, up_block, up_fnumlo,
|
busy_cnt <= 5'd0;
|
||||||
up_pms, up_dt1, up_tl, up_ks_ar,
|
|
||||||
up_amen_d1r,up_d2r, up_d1l, up_ssgeg } <= 11'd0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
else if(clk_en) begin
|
||||||
|
if( busy_cnt == 5'd31 ) busy <= 1'b0;
|
||||||
|
busy_cnt <= busy_cnt+5'd1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
jt12_reg u_reg(
|
jt12_reg #(.num_ch(num_ch)) u_reg(
|
||||||
.rst ( rst ),
|
.rst ( rst ),
|
||||||
.clk ( clk ), // P1
|
.clk ( clk ), // P1
|
||||||
.din ( din ),
|
.clk_en ( clk_en ),
|
||||||
|
.din ( din_copy ),
|
||||||
|
|
||||||
.up_keyon ( up_keyon ),
|
.up_keyon ( up_keyon ),
|
||||||
.up_alg ( up_alg ),
|
.up_fnumlo ( up_chreg[0] ),
|
||||||
.up_block ( up_block ),
|
.up_alg ( up_chreg[1] ),
|
||||||
.up_fnumlo ( up_fnumlo ),
|
.up_pms ( up_chreg[2] ),
|
||||||
.up_pms ( up_pms ),
|
.up_dt1 ( up_opreg[0] ),
|
||||||
.up_dt1 ( up_dt1 ),
|
.up_tl ( up_opreg[1] ),
|
||||||
.up_tl ( up_tl ),
|
.up_ks_ar ( up_opreg[2] ),
|
||||||
.up_ks_ar ( up_ks_ar ),
|
.up_amen_dr ( up_opreg[3] ),
|
||||||
.up_amen_d1r(up_amen_d1r),
|
.up_sr ( up_opreg[4] ),
|
||||||
.up_d2r ( up_d2r ),
|
.up_sl_rr ( up_opreg[5] ),
|
||||||
|
.up_ssgeg ( up_opreg[6] ),
|
||||||
.up_d1l ( up_d1l ),
|
|
||||||
.up_ssgeg ( up_ssgeg ),
|
|
||||||
|
|
||||||
.op ( up_op ), // operator to update
|
.op ( up_op ), // operator to update
|
||||||
.ch ( up_ch ), // channel to update
|
.ch ( up_ch ), // channel to update
|
||||||
@ -316,7 +338,6 @@ jt12_reg u_reg(
|
|||||||
.flag_A ( flag_A ),
|
.flag_A ( flag_A ),
|
||||||
.overflow_A ( overflow_A),
|
.overflow_A ( overflow_A),
|
||||||
|
|
||||||
.busy ( busy_reg ),
|
|
||||||
.ch6op ( ch6op ),
|
.ch6op ( ch6op ),
|
||||||
// CH3 Effect-mode operation
|
// CH3 Effect-mode operation
|
||||||
.effect ( effect ), // allows independent freq. for CH 3
|
.effect ( effect ), // allows independent freq. for CH 3
|
||||||
@ -326,40 +347,41 @@ jt12_reg u_reg(
|
|||||||
.block_ch3op2( block_ch3op2 ),
|
.block_ch3op2( block_ch3op2 ),
|
||||||
.block_ch3op3( block_ch3op3 ),
|
.block_ch3op3( block_ch3op3 ),
|
||||||
.block_ch3op1( block_ch3op1 ),
|
.block_ch3op1( block_ch3op1 ),
|
||||||
|
.latch_fnum ( latch_fnum ),
|
||||||
// Operator
|
// Operator
|
||||||
.use_prevprev1(use_prevprev1),
|
.xuse_prevprev1 ( xuse_prevprev1 ),
|
||||||
.use_internal_x(use_internal_x),
|
.xuse_internal ( xuse_internal ),
|
||||||
.use_internal_y(use_internal_y),
|
.yuse_internal ( yuse_internal ),
|
||||||
.use_prev2 ( use_prev2 ),
|
.xuse_prev2 ( xuse_prev2 ),
|
||||||
.use_prev1 ( use_prev1 ),
|
.yuse_prev1 ( yuse_prev1 ),
|
||||||
|
.yuse_prev2 ( yuse_prev2 ),
|
||||||
// PG
|
// PG
|
||||||
.fnum_I ( fnum_I ),
|
.fnum_I ( fnum_I ),
|
||||||
.block_I ( block_I ),
|
.block_I ( block_I ),
|
||||||
.mul_V ( mul_V ),
|
.mul_II ( mul_II ),
|
||||||
.dt1_II ( dt1_II ),
|
.dt1_I ( dt1_I ),
|
||||||
|
|
||||||
// EG
|
// EG
|
||||||
.ar_II (ar_II ), // attack rate
|
.ar_I (ar_I ), // attack rate
|
||||||
.d1r_II (d1r_II ), // decay rate
|
.d1r_I (d1r_I ), // decay rate
|
||||||
.d2r_II (d2r_II ), // sustain rate
|
.d2r_I (d2r_I ), // sustain rate
|
||||||
.rr_II (rr_II ), // release rate
|
.rr_I (rr_I ), // release rate
|
||||||
.d1l (d1l ), // sustain level
|
.sl_I (sl_I ), // sustain level
|
||||||
.ks_III (ks_III ), // key scale
|
.ks_II (ks_II ), // key scale
|
||||||
// SSG operation
|
// SSG operation
|
||||||
.ssg_en_II ( ssg_en_II ),
|
.ssg_en_I ( ssg_en_I ),
|
||||||
.ssg_eg_II ( ssg_eg_II ),
|
.ssg_eg_I ( ssg_eg_I ),
|
||||||
// envelope number
|
// envelope number
|
||||||
.tl_VII (tl_VII ),
|
.tl_IV (tl_IV ),
|
||||||
.pms (pms ),
|
.pms_I (pms_I ),
|
||||||
.ams_VII (ams_VII ),
|
.ams_IV (ams_IV ),
|
||||||
.amsen_VII (amsen_VII ),
|
.amsen_IV (amsen_IV ),
|
||||||
// channel configuration
|
// channel configuration
|
||||||
.rl ( rl ),
|
.rl ( rl ),
|
||||||
.fb_II ( fb_II ),
|
.fb_II ( fb_II ),
|
||||||
.alg ( alg ),
|
.alg_I ( alg_I ),
|
||||||
.keyon_II ( keyon_II ),
|
.keyon_I ( keyon_I ),
|
||||||
|
|
||||||
//.cur_op ( cur_op ),
|
|
||||||
.zero ( zero ),
|
.zero ( zero ),
|
||||||
.s1_enters ( s1_enters ),
|
.s1_enters ( s1_enters ),
|
||||||
.s2_enters ( s2_enters ),
|
.s2_enters ( s2_enters ),
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
`ifdef SIMULATION
|
`ifdef SIMULATION
|
||||||
|
/* verilator lint_off PINMISSING */
|
||||||
|
|
||||||
reg [4:0] sep24_cnt;
|
reg [4:0] sep24_cnt;
|
||||||
reg mmr_dump;
|
reg mmr_dump;
|
||||||
|
|
||||||
always @(posedge clk )
|
always @(posedge clk ) if(clk_en)
|
||||||
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
||||||
|
|
||||||
wire [10:0] fnum_ch0s1, fnum_ch1s1, fnum_ch2s1, fnum_ch3s1,
|
wire [10:0] fnum_ch0s1, fnum_ch1s1, fnum_ch2s1, fnum_ch3s1,
|
||||||
@ -16,8 +17,9 @@ wire [10:0] fnum_ch0s1, fnum_ch1s1, fnum_ch2s1, fnum_ch3s1,
|
|||||||
sep24 #( .width(11), .pos0(1) ) fnum_sep
|
sep24 #( .width(11), .pos0(1) ) fnum_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( fnum_I ),
|
.mixed ( fnum_I ),
|
||||||
.mask ( 11'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (fnum_ch0s1),
|
.ch0s1 (fnum_ch0s1),
|
||||||
@ -59,8 +61,9 @@ wire [2:0] block_ch0s1, block_ch1s1, block_ch2s1, block_ch3s1,
|
|||||||
sep24 #( .width(3), .pos0(1) ) block_sep
|
sep24 #( .width(3), .pos0(1) ) block_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( block_I ),
|
.mixed ( block_I ),
|
||||||
.mask ( 3'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (block_ch0s1),
|
.ch0s1 (block_ch0s1),
|
||||||
@ -102,8 +105,9 @@ wire [1:0] rl_ch0s1, rl_ch1s1, rl_ch2s1, rl_ch3s1,
|
|||||||
sep24 #( .width(2), .pos0(1) ) rl_sep
|
sep24 #( .width(2), .pos0(1) ) rl_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( rl ),
|
.mixed ( rl ),
|
||||||
.mask ( 2'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (rl_ch0s1),
|
.ch0s1 (rl_ch0s1),
|
||||||
@ -145,8 +149,9 @@ wire [2:0] fb_ch0s1, fb_ch1s1, fb_ch2s1, fb_ch3s1,
|
|||||||
sep24 #( .width(3), .pos0(0) ) fb_sep
|
sep24 #( .width(3), .pos0(0) ) fb_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( fb_II ),
|
.mixed ( fb_II ),
|
||||||
.mask ( 3'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (fb_ch0s1),
|
.ch0s1 (fb_ch0s1),
|
||||||
@ -188,8 +193,9 @@ wire [2:0] alg_ch0s1, alg_ch1s1, alg_ch2s1, alg_ch3s1,
|
|||||||
sep24 #( .width(3), .pos0(1) ) alg_sep
|
sep24 #( .width(3), .pos0(1) ) alg_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( alg ),
|
.mixed ( alg ),
|
||||||
.mask ( 3'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (alg_ch0s1),
|
.ch0s1 (alg_ch0s1),
|
||||||
@ -231,8 +237,9 @@ wire [2:0] dt1_ch0s1, dt1_ch1s1, dt1_ch2s1, dt1_ch3s1,
|
|||||||
sep24 #( .width(3), .pos0(0) ) dt1_sep
|
sep24 #( .width(3), .pos0(0) ) dt1_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( dt1_II ),
|
.mixed ( dt1_II ),
|
||||||
.mask ( 3'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (dt1_ch0s1),
|
.ch0s1 (dt1_ch0s1),
|
||||||
@ -274,8 +281,9 @@ wire [3:0] mul_ch0s1, mul_ch1s1, mul_ch2s1, mul_ch3s1,
|
|||||||
sep24 #( .width(4), .pos0(21) ) mul_sep
|
sep24 #( .width(4), .pos0(21) ) mul_sep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( mul_V ),
|
.mixed ( mul_V ),
|
||||||
.mask ( 4'd0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (mul_ch0s1),
|
.ch0s1 (mul_ch0s1),
|
||||||
@ -314,11 +322,12 @@ wire [6:0] tl_ch0s1, tl_ch1s1, tl_ch2s1, tl_ch3s1,
|
|||||||
tl_ch4s3, tl_ch5s3, tl_ch0s4, tl_ch1s4,
|
tl_ch4s3, tl_ch5s3, tl_ch0s4, tl_ch1s4,
|
||||||
tl_ch2s4, tl_ch3s4, tl_ch4s4, tl_ch5s4;
|
tl_ch2s4, tl_ch3s4, tl_ch4s4, tl_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(7), .pos0(19) ) tl_step
|
sep24 #( .width(7), .pos0(22) ) tl_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( tl_VII ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 7'd0 ),
|
.mixed ( tl_IV ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (tl_ch0s1),
|
.ch0s1 (tl_ch0s1),
|
||||||
@ -357,11 +366,12 @@ wire [4:0] ar_ch0s1, ar_ch1s1, ar_ch2s1, ar_ch3s1,
|
|||||||
ar_ch4s3, ar_ch5s3, ar_ch0s4, ar_ch1s4,
|
ar_ch4s3, ar_ch5s3, ar_ch0s4, ar_ch1s4,
|
||||||
ar_ch2s4, ar_ch3s4, ar_ch4s4, ar_ch5s4;
|
ar_ch2s4, ar_ch3s4, ar_ch4s4, ar_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(5), .pos0(0) ) ar_step
|
sep24 #( .width(5), .pos0(1) ) ar_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( ar_II ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 5'd0 ),
|
.mixed ( ar_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (ar_ch0s1),
|
.ch0s1 (ar_ch0s1),
|
||||||
@ -400,11 +410,12 @@ wire [4:0] d1r_ch0s1, d1r_ch1s1, d1r_ch2s1, d1r_ch3s1,
|
|||||||
d1r_ch4s3, d1r_ch5s3, d1r_ch0s4, d1r_ch1s4,
|
d1r_ch4s3, d1r_ch5s3, d1r_ch0s4, d1r_ch1s4,
|
||||||
d1r_ch2s4, d1r_ch3s4, d1r_ch4s4, d1r_ch5s4;
|
d1r_ch2s4, d1r_ch3s4, d1r_ch4s4, d1r_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(5), .pos0(0) ) d1r_step
|
sep24 #( .width(5), .pos0(1) ) d1r_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( d1r_II ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 0 ),
|
.mixed ( d1r_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (d1r_ch0s1),
|
.ch0s1 (d1r_ch0s1),
|
||||||
@ -443,11 +454,12 @@ wire [4:0] d2r_ch0s1, d2r_ch1s1, d2r_ch2s1, d2r_ch3s1,
|
|||||||
d2r_ch4s3, d2r_ch5s3, d2r_ch0s4, d2r_ch1s4,
|
d2r_ch4s3, d2r_ch5s3, d2r_ch0s4, d2r_ch1s4,
|
||||||
d2r_ch2s4, d2r_ch3s4, d2r_ch4s4, d2r_ch5s4;
|
d2r_ch2s4, d2r_ch3s4, d2r_ch4s4, d2r_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(5), .pos0(0) ) d2r_step
|
sep24 #( .width(5), .pos0(1) ) d2r_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( d2r_II ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 5'd0 ),
|
.mixed ( d2r_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (d2r_ch0s1),
|
.ch0s1 (d2r_ch0s1),
|
||||||
@ -486,11 +498,12 @@ wire [3:0] rr_ch0s1, rr_ch1s1, rr_ch2s1, rr_ch3s1,
|
|||||||
rr_ch4s3, rr_ch5s3, rr_ch0s4, rr_ch1s4,
|
rr_ch4s3, rr_ch5s3, rr_ch0s4, rr_ch1s4,
|
||||||
rr_ch2s4, rr_ch3s4, rr_ch4s4, rr_ch5s4;
|
rr_ch2s4, rr_ch3s4, rr_ch4s4, rr_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(4), .pos0(0) ) rr_step
|
sep24 #( .width(4), .pos0(1) ) rr_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( rr_II ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 0 ),
|
.mixed ( rr_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (rr_ch0s1),
|
.ch0s1 (rr_ch0s1),
|
||||||
@ -532,8 +545,9 @@ wire [3:0] d1l_ch0s1, d1l_ch1s1, d1l_ch2s1, d1l_ch3s1,
|
|||||||
sep24 #( .width(4), .pos0(1) ) d1l_step
|
sep24 #( .width(4), .pos0(1) ) d1l_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( d1l ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 4'd0 ),
|
.mixed ( sl_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (d1l_ch0s1),
|
.ch0s1 (d1l_ch0s1),
|
||||||
@ -572,11 +586,12 @@ wire [1:0] ks_ch0s1, ks_ch1s1, ks_ch2s1, ks_ch3s1,
|
|||||||
ks_ch4s3, ks_ch5s3, ks_ch0s4, ks_ch1s4,
|
ks_ch4s3, ks_ch5s3, ks_ch0s4, ks_ch1s4,
|
||||||
ks_ch2s4, ks_ch3s4, ks_ch4s4, ks_ch5s4;
|
ks_ch2s4, ks_ch3s4, ks_ch4s4, ks_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(2), .pos0(23) ) ks_step
|
sep24 #( .width(2), .pos0(0) ) ks_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( ks_III ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 0 ),
|
.mixed ( ks_II ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (ks_ch0s1),
|
.ch0s1 (ks_ch0s1),
|
||||||
@ -608,7 +623,7 @@ sep24 #( .width(2), .pos0(23) ) ks_step
|
|||||||
.ch5s4 (ks_ch5s4)
|
.ch5s4 (ks_ch5s4)
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [3:0] ssg_II = {ssg_en_II, ssg_eg_II};
|
wire [3:0] ssg_I = {ssg_en_I, ssg_eg_I};
|
||||||
|
|
||||||
wire [3:0] ssg_ch0s1, ssg_ch1s1, ssg_ch2s1, ssg_ch3s1,
|
wire [3:0] ssg_ch0s1, ssg_ch1s1, ssg_ch2s1, ssg_ch3s1,
|
||||||
ssg_ch4s1, ssg_ch5s1, ssg_ch0s2, ssg_ch1s2,
|
ssg_ch4s1, ssg_ch5s1, ssg_ch0s2, ssg_ch1s2,
|
||||||
@ -617,11 +632,12 @@ wire [3:0] ssg_ch0s1, ssg_ch1s1, ssg_ch2s1, ssg_ch3s1,
|
|||||||
ssg_ch4s3, ssg_ch5s3, ssg_ch0s4, ssg_ch1s4,
|
ssg_ch4s3, ssg_ch5s3, ssg_ch0s4, ssg_ch1s4,
|
||||||
ssg_ch2s4, ssg_ch3s4, ssg_ch4s4, ssg_ch5s4;
|
ssg_ch2s4, ssg_ch3s4, ssg_ch4s4, ssg_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(4), .pos0(0) ) ssg_step
|
sep24 #( .width(4), .pos0(1) ) ssg_step
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( ssg_II ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 4'd0 ),
|
.mixed ( ssg_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (ssg_ch0s1),
|
.ch0s1 (ssg_ch0s1),
|
||||||
@ -660,11 +676,12 @@ wire kon_ch0s1, kon_ch1s1, kon_ch2s1, kon_ch3s1,
|
|||||||
kon_ch4s3, kon_ch5s3, kon_ch0s4, kon_ch1s4,
|
kon_ch4s3, kon_ch5s3, kon_ch0s4, kon_ch1s4,
|
||||||
kon_ch2s4, kon_ch3s4, kon_ch4s4, kon_ch5s4;
|
kon_ch2s4, kon_ch3s4, kon_ch4s4, kon_ch5s4;
|
||||||
|
|
||||||
sep24 #( .width(1), .pos0(0) ) konstep
|
sep24 #( .width(1), .pos0(1) ) konstep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.mixed ( keyon_II ),
|
.clk_en ( clk_en ),
|
||||||
.mask ( 1'd0 ),
|
.mixed ( keyon_I ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (kon_ch0s1),
|
.ch0s1 (kon_ch0s1),
|
||||||
@ -699,7 +716,7 @@ sep24 #( .width(1), .pos0(0) ) konstep
|
|||||||
/* Dump all registers on request */
|
/* Dump all registers on request */
|
||||||
integer fmmr;
|
integer fmmr;
|
||||||
initial begin
|
initial begin
|
||||||
fmmr=$fopen("mmr_dump.log");
|
fmmr=$fopen("mmr_dump.log","w");
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
@ -832,5 +849,6 @@ if (mmr_dump ) begin
|
|||||||
d2r_ch5s4, rr_ch5s4, d1l_ch5s4, ks_ch5s4, ssg_ch5s4,
|
d2r_ch5s4, rr_ch5s4, d1l_ch5s4, ks_ch5s4, ssg_ch5s4,
|
||||||
kon_ch5s4 );
|
kon_ch5s4 );
|
||||||
end
|
end
|
||||||
|
/* verilator lint_on PINMISSING */
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
@ -31,92 +31,125 @@ module jt12_mod(
|
|||||||
|
|
||||||
input [2:0] alg_I,
|
input [2:0] alg_I,
|
||||||
|
|
||||||
output reg use_prevprev1,
|
output reg xuse_prevprev1,
|
||||||
output reg use_internal_x,
|
output reg xuse_internal,
|
||||||
output reg use_internal_y,
|
output reg yuse_internal,
|
||||||
output reg use_prev2,
|
output reg xuse_prev2,
|
||||||
output reg use_prev1
|
output reg yuse_prev1,
|
||||||
|
output reg yuse_prev2
|
||||||
);
|
);
|
||||||
|
|
||||||
|
parameter num_ch=6;
|
||||||
|
|
||||||
reg [7:0] alg_hot;
|
reg [7:0] alg_hot;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
case( alg_I )
|
case( alg_I )
|
||||||
3'd0: alg_hot <= 8'h1; // D0
|
3'd0: alg_hot = 8'h1; // D0
|
||||||
3'd1: alg_hot <= 8'h2; // D1
|
3'd1: alg_hot = 8'h2; // D1
|
||||||
3'd2: alg_hot <= 8'h4; // D2
|
3'd2: alg_hot = 8'h4; // D2
|
||||||
3'd3: alg_hot <= 8'h8; // D3
|
3'd3: alg_hot = 8'h8; // D3
|
||||||
3'd4: alg_hot <= 8'h10; // D4
|
3'd4: alg_hot = 8'h10; // D4
|
||||||
3'd5: alg_hot <= 8'h20; // D5
|
3'd5: alg_hot = 8'h20; // D5
|
||||||
3'd6: alg_hot <= 8'h40; // D6
|
3'd6: alg_hot = 8'h40; // D6
|
||||||
3'd7: alg_hot <= 8'h80; // D7
|
3'd7: alg_hot = 8'h80; // D7
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// prev2 cannot modulate with prevprev1 at the same time
|
||||||
|
// x = prev2, prevprev1, internal_x
|
||||||
|
// y = prev1, internal_y
|
||||||
|
|
||||||
|
generate
|
||||||
|
if( num_ch==6 ) begin
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
use_prevprev1 <= s1_enters | (s3_enters&alg_hot[5]);
|
xuse_prevprev1 = s1_enters | (s3_enters&alg_hot[5]);
|
||||||
use_prev2 <= (s3_enters&(|alg_hot[2:0])) | (s4_enters&alg_hot[3]);
|
xuse_prev2 = (s3_enters&(|alg_hot[2:0])) | (s4_enters&alg_hot[3]);
|
||||||
use_internal_x <= s4_enters & alg_hot[2];
|
xuse_internal = s4_enters & alg_hot[2];
|
||||||
use_internal_y <= s4_enters & (|{alg_hot[4:3],alg_hot[1:0]});
|
yuse_internal = s4_enters & (|{alg_hot[4:3],alg_hot[1:0]});
|
||||||
use_prev1 <= s1_enters | (s3_enters&alg_hot[1]) |
|
yuse_prev1 = s1_enters | (s3_enters&alg_hot[1]) |
|
||||||
(s2_enters&(|{alg_hot[6:3],alg_hot[0]}) )|
|
(s2_enters&(|{alg_hot[6:3],alg_hot[0]}) )|
|
||||||
(s4_enters&(|{alg_hot[5],alg_hot[2]}));
|
(s4_enters&(|{alg_hot[5],alg_hot[2]}));
|
||||||
|
yuse_prev2 = 1'b0; // unused for 6 channels
|
||||||
end
|
end
|
||||||
|
end else begin
|
||||||
/*
|
reg [2:0] xuse_s4, xuse_s3, xuse_s2, xuse_s1;
|
||||||
always @(*) begin
|
reg [2:0] yuse_s4, yuse_s3, yuse_s2, yuse_s1;
|
||||||
use_prevprev1 <= s1_enters || (s3_enters&&(alg_I==3'd5));
|
always @(*) begin // 3 ch
|
||||||
use_prev2 <= (s3_enters&&(alg_I<=3'd2)) || (s4_enters&&(alg_I==3'd3));
|
// S1
|
||||||
use_internal_x <= s4_enters && (alg_I==3'd2);
|
{ xuse_s1, yuse_s1 } = { 3'b001, 3'b100 };
|
||||||
use_internal_y <= s4_enters && (alg_I<=3'd4 && alg_I!=3'd2);
|
// S2
|
||||||
use_prev1 <= s1_enters || (s3_enters&&(alg_I==3'd1)) ||
|
casez( 1'b1 )
|
||||||
(s2_enters&&(alg_I==3'd0 ||
|
// S2 modulated by S1
|
||||||
alg_I==3'd3 || alg_I==3'd4 ||
|
alg_hot[6], alg_hot[5], alg_hot[4], alg_hot[3], alg_hot[0]:
|
||||||
alg_I==3'd5 || alg_I==3'd6)) ||
|
{ xuse_s2, yuse_s2 } = { 3'b000, 3'b100 }; // prev1
|
||||||
(s4_enters&&(alg_I==3'd2 || alg_I==3'd5));
|
default: { xuse_s2, yuse_s2 } = 6'd0;
|
||||||
|
endcase
|
||||||
|
// S3
|
||||||
|
casez( 1'b1 )
|
||||||
|
// S3 modulated by S1
|
||||||
|
alg_hot[5]:
|
||||||
|
{ xuse_s3, yuse_s3 } = { 3'b000, 3'b100 }; // prev1
|
||||||
|
// S3 modulated by S2
|
||||||
|
alg_hot[2], alg_hot[0]:
|
||||||
|
{ xuse_s3, yuse_s3 } = { 3'b000, 3'b010 }; // prev2
|
||||||
|
// S3 modulated by S2+S1
|
||||||
|
alg_hot[1]:
|
||||||
|
{ xuse_s3, yuse_s3 } = { 3'b010, 3'b100 }; // prev2 + prev1
|
||||||
|
default: { xuse_s3, yuse_s3 } = 6'd0;
|
||||||
|
endcase
|
||||||
|
// S4
|
||||||
|
casez( 1'b1 )
|
||||||
|
// S4 modulated by S1
|
||||||
|
alg_hot[5]:
|
||||||
|
{ xuse_s4, yuse_s4 } = { 3'b000, 3'b100 }; // prev1
|
||||||
|
// S4 modulated by S3
|
||||||
|
alg_hot[4], alg_hot[1], alg_hot[0]:
|
||||||
|
{ xuse_s4, yuse_s4 } = { 3'b100, 3'b000 }; // prevprev1
|
||||||
|
// S4 modulated by S3+S2
|
||||||
|
alg_hot[3]:
|
||||||
|
{ xuse_s4, yuse_s4 } = { 3'b100, 3'b010 }; // prevprev1+prev2
|
||||||
|
// S4 modulated by S3+S1
|
||||||
|
alg_hot[2]:
|
||||||
|
{ xuse_s4, yuse_s4 } = { 3'b100, 3'b100 }; // prevprev1+prev1
|
||||||
|
default: { xuse_s4, yuse_s4 } = 6'd0;
|
||||||
|
endcase
|
||||||
|
case( {s4_enters, s3_enters, s2_enters, s1_enters})
|
||||||
|
4'b1000: begin
|
||||||
|
{xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s4;
|
||||||
|
{yuse_prev1, yuse_prev2, yuse_internal } = yuse_s4;
|
||||||
end
|
end
|
||||||
|
4'b0100: begin
|
||||||
always @(*) begin
|
{xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s3;
|
||||||
case( {s1_enters, s3_enters, s2_enters, s4_enters} ) // synthesis parallel_case
|
{yuse_prev1, yuse_prev2, yuse_internal } = yuse_s3;
|
||||||
4'b1000: begin // S1
|
|
||||||
use_prevprev1 <= 1'b1;
|
|
||||||
use_prev2 <= 1'b0;
|
|
||||||
use_internal_x<= 1'b0;
|
|
||||||
use_internal_y<= 1'b0;
|
|
||||||
use_prev1 <= 1'b1;
|
|
||||||
end
|
end
|
||||||
4'b0100: begin // S3
|
4'b0010: begin
|
||||||
use_prevprev1 <= alg_I==3'd5;
|
{xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s2;
|
||||||
use_prev2 <= (alg_I<=3'd2);
|
{yuse_prev1, yuse_prev2, yuse_internal } = yuse_s2;
|
||||||
use_internal_x<= 1'b0;
|
|
||||||
use_internal_y<= 1'b0;
|
|
||||||
use_prev1 <= alg_I==3'd1;
|
|
||||||
end
|
end
|
||||||
4'b0010: begin // S2
|
4'b0001: begin
|
||||||
use_prevprev1 <= 1'b0;
|
{xuse_prevprev1, xuse_prev2, xuse_internal} = xuse_s1;
|
||||||
use_prev2 <= 1'b0;
|
{yuse_prev1, yuse_prev2, yuse_internal } = yuse_s1;
|
||||||
use_internal_x<= 1'b0;
|
|
||||||
use_prev1 <= (alg_I==3'd0 ||
|
|
||||||
alg_I==3'd3 || alg_I==3'd4 ||
|
|
||||||
alg_I==3'd5 || alg_I==3'd6 );
|
|
||||||
use_internal_y<= 1'b0;
|
|
||||||
end
|
|
||||||
4'b0001: begin // S4
|
|
||||||
use_prevprev1 <= 1'b0;
|
|
||||||
use_prev2 <= ( alg_I==3'd3 );
|
|
||||||
use_internal_x <= alg_I==3'd2;
|
|
||||||
use_prev1 <= (alg_I==3'd2 || alg_I==3'd5);
|
|
||||||
use_internal_y <= ( alg_I<=3'd4 && alg_I!=3'd2);
|
|
||||||
end
|
end
|
||||||
default: begin
|
default: begin
|
||||||
use_prevprev1 <= 1'bx;
|
{xuse_prevprev1, xuse_prev2, xuse_internal} = 3'b0;
|
||||||
use_prev2 <= 1'bx;
|
{yuse_prev1, yuse_prev2, yuse_internal } = 3'b0;
|
||||||
use_internal_x<= 1'bx;
|
|
||||||
use_prev1 <= 1'bx;
|
|
||||||
use_internal_y<= 1'bx;
|
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
*/
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
`ifdef SIMULATION
|
||||||
|
// Control signals for simulation: should be 2'b0 or 2'b1
|
||||||
|
wire [1:0] xusage = xuse_prevprev1+xuse_prev2+xuse_internal;
|
||||||
|
wire [1:0] yusage = yuse_prev1+yuse_internal;
|
||||||
|
|
||||||
|
always @(xusage,yusage)
|
||||||
|
if( xusage>2'b1 || yusage>2'b1 ) begin
|
||||||
|
$display("ERROR: x/y over use in jt12_mod");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -29,14 +29,16 @@
|
|||||||
module jt12_op(
|
module jt12_op(
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input [9:0] pg_phase_VIII,
|
input [9:0] pg_phase_VIII,
|
||||||
input [9:0] eg_atten_IX, // output from envelope generator
|
input [9:0] eg_atten_IX, // output from envelope generator
|
||||||
input [2:0] fb_II, // voice feedback
|
input [2:0] fb_II, // voice feedback
|
||||||
input use_prevprev1,
|
input xuse_prevprev1,
|
||||||
input use_internal_x,
|
input xuse_prev2,
|
||||||
input use_internal_y,
|
input xuse_internal,
|
||||||
input use_prev2,
|
input yuse_prev1,
|
||||||
input use_prev1,
|
input yuse_prev2,
|
||||||
|
input yuse_internal,
|
||||||
input test_214,
|
input test_214,
|
||||||
|
|
||||||
input s1_enters,
|
input s1_enters,
|
||||||
@ -45,7 +47,8 @@ module jt12_op(
|
|||||||
input s4_enters,
|
input s4_enters,
|
||||||
input zero,
|
input zero,
|
||||||
|
|
||||||
output signed [8:0] op_result
|
output signed [ 8:0] op_result,
|
||||||
|
output signed [13:0] full_result
|
||||||
);
|
);
|
||||||
|
|
||||||
/* enters exits
|
/* enters exits
|
||||||
@ -59,45 +62,55 @@ reg [13:0] op_result_internal, op_XII;
|
|||||||
reg [11:0] atten_internal_IX;
|
reg [11:0] atten_internal_IX;
|
||||||
|
|
||||||
assign op_result = op_result_internal[13:5];
|
assign op_result = op_result_internal[13:5];
|
||||||
|
assign full_result = op_result_internal;
|
||||||
|
|
||||||
parameter NUM_VOICES = 6;
|
parameter num_ch = 6;
|
||||||
|
|
||||||
reg signbit_IX, signbit_X, signbit_XI;
|
reg signbit_IX, signbit_X, signbit_XI;
|
||||||
reg [11:0] totalatten_X;
|
reg [11:0] totalatten_X;
|
||||||
|
|
||||||
wire [13:0] prev1, prevprev1, prev2;
|
wire [13:0] prev1, prevprev1, prev2;
|
||||||
|
|
||||||
jt12_sh/*_rst*/ #( .width(14), .stages(NUM_VOICES)) prev1_buffer(
|
reg [13:0] prev1_din, prevprev1_din, prev2_din;
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
if( num_ch==3 ) begin
|
||||||
|
prev1_din = s1_enters ? op_result_internal : prev1;
|
||||||
|
prevprev1_din = s3_enters ? op_result_internal : prevprev1;
|
||||||
|
prev2_din = s2_enters ? op_result_internal : prev2;
|
||||||
|
end else begin // 6 channels
|
||||||
|
prev1_din = s2_enters ? op_result_internal : prev1;
|
||||||
|
prevprev1_din = s2_enters ? prev1 : prevprev1;
|
||||||
|
prev2_din = s1_enters ? op_result_internal : prev2;
|
||||||
|
end
|
||||||
|
|
||||||
|
jt12_sh #( .width(14), .stages(num_ch)) prev1_buffer(
|
||||||
// .rst ( rst ),
|
// .rst ( rst ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( s2_enters ? op_result_internal : prev1 ),
|
.clk_en ( clk_en ),
|
||||||
|
.din ( prev1_din ),
|
||||||
.drop ( prev1 )
|
.drop ( prev1 )
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh/*_rst*/ #( .width(14), .stages(NUM_VOICES)) prevprev1_buffer(
|
jt12_sh #( .width(14), .stages(num_ch)) prevprev1_buffer(
|
||||||
// .rst ( rst ),
|
// .rst ( rst ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( s2_enters ? prev1 : prevprev1 ),
|
.clk_en ( clk_en ),
|
||||||
|
.din ( prevprev1_din ),
|
||||||
.drop ( prevprev1 )
|
.drop ( prevprev1 )
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh/*_rst*/ #( .width(14), .stages(NUM_VOICES)) prev2_buffer(
|
jt12_sh #( .width(14), .stages(num_ch)) prev2_buffer(
|
||||||
// .rst ( rst ),
|
// .rst ( rst ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( s1_enters ? op_result_internal : prev2 ),
|
.clk_en ( clk_en ),
|
||||||
|
.din ( prev2_din ),
|
||||||
.drop ( prev2 )
|
.drop ( prev2 )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
reg [18:0] stb;
|
|
||||||
reg [10:0] stf, stg;
|
|
||||||
reg [11:0] logsin;
|
|
||||||
reg [10:0] subtresult;
|
reg [10:0] subtresult;
|
||||||
|
|
||||||
reg [12:0] etb;
|
|
||||||
reg [ 9:0] etf, etg, mantissa_XI;
|
|
||||||
reg [ 3:0] exponent_XI;
|
|
||||||
|
|
||||||
reg [12:0] shifter, shifter_2, shifter_3;
|
reg [12:0] shifter, shifter_2, shifter_3;
|
||||||
|
|
||||||
// REGISTER/CYCLE 1
|
// REGISTER/CYCLE 1
|
||||||
@ -107,17 +120,23 @@ reg [14:0] xs, ys, pm_preshift_II;
|
|||||||
reg s1_II;
|
reg s1_II;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
|
casez( {xuse_prevprev1, xuse_prev2, xuse_internal })
|
||||||
x <= ( {14{use_prevprev1}} & prevprev1 ) |
|
3'b1??: x = prevprev1;
|
||||||
( {14{use_internal_x}} & op_result_internal ) |
|
3'b01?: x = prev2;
|
||||||
( {14{use_prev2}} & prev2 );
|
3'b001: x = op_result_internal;
|
||||||
y <= ( {14{use_prev1}} & prev1 ) |
|
default: x = 14'd0;
|
||||||
( {14{use_internal_y}} & op_result_internal );
|
endcase
|
||||||
xs <= { x[13], x }; // sign-extend
|
casez( {yuse_prev1, yuse_prev2, yuse_internal })
|
||||||
ys <= { y[13], y }; // sign-extend
|
3'b1??: y = prev1;
|
||||||
|
3'b01?: y = prev2;
|
||||||
|
3'b001: y = op_result_internal;
|
||||||
|
default: y = 14'd0;
|
||||||
|
endcase
|
||||||
|
xs = { x[13], x }; // sign-extend
|
||||||
|
ys = { y[13], y }; // sign-extend
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if( clk_en ) begin
|
||||||
pm_preshift_II <= xs + ys; // carry is discarded
|
pm_preshift_II <= xs + ys; // carry is discarded
|
||||||
s1_II <= s1_enters;
|
s1_II <= s1_enters;
|
||||||
end
|
end
|
||||||
@ -135,26 +154,33 @@ wire [9:0] phasemod_VIII;
|
|||||||
always @(*) begin
|
always @(*) begin
|
||||||
// Shift FM feedback signal
|
// Shift FM feedback signal
|
||||||
if (!s1_II ) // Not S1
|
if (!s1_II ) // Not S1
|
||||||
phasemod_II <= pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used
|
phasemod_II = pm_preshift_II[10:1]; // Bit 0 of pm_preshift_II is never used
|
||||||
else // S1
|
else // S1
|
||||||
case( fb_II )
|
case( fb_II )
|
||||||
3'd0: phasemod_II <= 10'd0;
|
3'd0: phasemod_II = 10'd0;
|
||||||
3'd1: phasemod_II <= { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] };
|
3'd1: phasemod_II = { {4{pm_preshift_II[14]}}, pm_preshift_II[14:9] };
|
||||||
3'd2: phasemod_II <= { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] };
|
3'd2: phasemod_II = { {3{pm_preshift_II[14]}}, pm_preshift_II[14:8] };
|
||||||
3'd3: phasemod_II <= { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] };
|
3'd3: phasemod_II = { {2{pm_preshift_II[14]}}, pm_preshift_II[14:7] };
|
||||||
3'd4: phasemod_II <= { pm_preshift_II[14], pm_preshift_II[14:6] };
|
3'd4: phasemod_II = { pm_preshift_II[14], pm_preshift_II[14:6] };
|
||||||
3'd5: phasemod_II <= pm_preshift_II[14:5];
|
3'd5: phasemod_II = pm_preshift_II[14:5];
|
||||||
3'd6: phasemod_II <= pm_preshift_II[13:4];
|
3'd6: phasemod_II = pm_preshift_II[13:4];
|
||||||
3'd7: phasemod_II <= pm_preshift_II[12:3];
|
3'd7: phasemod_II = pm_preshift_II[12:3];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
// REGISTER/CYCLE 2-7
|
// REGISTER/CYCLE 2-7
|
||||||
jt12_sh #( .width(10), .stages(NUM_VOICES)) phasemod_sh(
|
//generate
|
||||||
|
// if( num_ch==6 )
|
||||||
|
jt12_sh #( .width(10), .stages(6)) phasemod_sh(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en),
|
||||||
.din ( phasemod_II ),
|
.din ( phasemod_II ),
|
||||||
.drop ( phasemod_VIII )
|
.drop ( phasemod_VIII )
|
||||||
);
|
);
|
||||||
|
// else begin
|
||||||
|
// assign phasemod_VIII = phasemod_II;
|
||||||
|
// end
|
||||||
|
// endgenerate
|
||||||
|
|
||||||
// REGISTER/CYCLE 8
|
// REGISTER/CYCLE 8
|
||||||
reg [ 9:0] phase;
|
reg [ 9:0] phase;
|
||||||
@ -163,119 +189,55 @@ reg [ 9:0] phase;
|
|||||||
// the fanouts among the duplicates until the fanout of each cell
|
// the fanouts among the duplicates until the fanout of each cell
|
||||||
// is below the maximum.
|
// is below the maximum.
|
||||||
|
|
||||||
reg [ 7:0] phaselo_IX, aux_VIII;
|
reg [ 7:0] aux_VIII;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
phase <= phasemod_VIII + pg_phase_VIII;
|
phase = phasemod_VIII + pg_phase_VIII;
|
||||||
aux_VIII<= phase[7:0] ^ {8{~phase[8]}};
|
aux_VIII= phase[7:0] ^ {8{~phase[8]}};
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if( clk_en ) begin
|
||||||
phaselo_IX <= aux_VIII;
|
|
||||||
signbit_IX <= phase[9];
|
signbit_IX <= phase[9];
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
wire [45:0] sta_IX;
|
wire [11:0] logsin_IX;
|
||||||
|
|
||||||
jt12_phrom u_phrom(
|
jt12_logsin u_logsin (
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.addr ( aux_VIII[5:1] ),
|
.clk_en ( clk_en ),
|
||||||
.ph ( sta_IX )
|
.addr ( aux_VIII[7:0] ),
|
||||||
|
.logsin ( logsin_IX )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// REGISTER/CYCLE 9
|
// REGISTER/CYCLE 9
|
||||||
// Sine table
|
// Sine table
|
||||||
// Main sine table body
|
// Main sine table body
|
||||||
|
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
//sta_IX <= sinetable[ phaselo_IX[5:1] ];
|
subtresult = eg_atten_IX + logsin_IX[11:2];
|
||||||
// 2-bit row chooser
|
atten_internal_IX = { subtresult[9:0], logsin_IX[1:0] } | {12{subtresult[10]}};
|
||||||
case( phaselo_IX[7:6] )
|
|
||||||
2'b00: stb <= { 10'b0, sta_IX[29], sta_IX[25], 2'b0, sta_IX[18],
|
|
||||||
sta_IX[14], 1'b0, sta_IX[7] , sta_IX[3] };
|
|
||||||
2'b01: stb <= { 6'b0 , sta_IX[37], sta_IX[34], 2'b0, sta_IX[28],
|
|
||||||
sta_IX[24], 2'b0, sta_IX[17], sta_IX[13], sta_IX[10], sta_IX[6], sta_IX[2] };
|
|
||||||
2'b10: stb <= { 2'b0, sta_IX[43], sta_IX[41], 2'b0, sta_IX[36],
|
|
||||||
sta_IX[33], 2'b0, sta_IX[27], sta_IX[23], 1'b0, sta_IX[20],
|
|
||||||
sta_IX[16], sta_IX[12], sta_IX[9], sta_IX[5], sta_IX[1] };
|
|
||||||
default: stb <= {
|
|
||||||
sta_IX[45], sta_IX[44], sta_IX[42], sta_IX[40]
|
|
||||||
, sta_IX[39], sta_IX[38], sta_IX[35], sta_IX[32]
|
|
||||||
, sta_IX[31], sta_IX[30], sta_IX[26], sta_IX[22]
|
|
||||||
, sta_IX[21], sta_IX[19], sta_IX[15], sta_IX[11]
|
|
||||||
, sta_IX[8], sta_IX[4], sta_IX[0] };
|
|
||||||
endcase
|
|
||||||
// Fixed value to sum
|
|
||||||
stf <= { stb[18:15], stb[12:11], stb[8:7], stb[4:3], stb[0] };
|
|
||||||
// Gated value to sum; bit 14 is indeed used twice
|
|
||||||
if( phaselo_IX[0] )
|
|
||||||
stg <= { 2'b0, stb[14], stb[14:13], stb[10:9], stb[6:5], stb[2:1] };
|
|
||||||
else
|
|
||||||
stg <= 11'd0;
|
|
||||||
// Sum to produce final logsin value
|
|
||||||
logsin <= stf + stg; // Carry-out of 11-bit addition becomes 12th bit
|
|
||||||
// Invert-subtract logsin value from EG attenuation value, with inverted carry
|
|
||||||
// In the actual chip, the output of the above logsin sum is already inverted.
|
|
||||||
// The two LSBs go through inverters (so they're non-inverted); the eg_atten_IX signal goes through inverters.
|
|
||||||
// The adder is normal except the carry-in is 1. It's a 10-bit adder.
|
|
||||||
// The outputs are inverted outputs, including the carry bit.
|
|
||||||
//subtresult <= not (('0' & not eg_atten_IX) - ('1' & logsin([11:2])));
|
|
||||||
// After a little pencil-and-paper, turns out this is equivalent to a regular adder!
|
|
||||||
subtresult <= eg_atten_IX + logsin[11:2];
|
|
||||||
// Place all but carry bit into result; also two LSBs of logsin
|
|
||||||
// If addition overflowed, make it the largest value (saturate)
|
|
||||||
atten_internal_IX <= { subtresult[9:0], logsin[1:0] } | {12{subtresult[10]}};
|
|
||||||
end
|
end
|
||||||
|
|
||||||
wire [44:0] exp_X;
|
wire [9:0] mantissa_X;
|
||||||
|
reg [9:0] mantissa_XI;
|
||||||
|
reg [3:0] exponent_X, exponent_XI;
|
||||||
|
|
||||||
jt12_exprom u_exprom(
|
jt12_exprom u_exprom(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.addr ( atten_internal_IX[5:1] ),
|
.clk_en ( clk_en ),
|
||||||
.exp ( exp_X )
|
.addr ( atten_internal_IX[7:0] ),
|
||||||
|
.exp ( mantissa_X )
|
||||||
);
|
);
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if( clk_en ) begin
|
||||||
totalatten_X <= atten_internal_IX;
|
exponent_X <= atten_internal_IX[11:8];
|
||||||
signbit_X <= signbit_IX;
|
signbit_X <= signbit_IX;
|
||||||
end
|
end
|
||||||
|
|
||||||
//wire [1:0] et_sel = totalatten_X[7:6];
|
always @(posedge clk) if( clk_en ) begin
|
||||||
//wire [4:0] et_fine = totalatten_X[5:1];
|
mantissa_XI <= mantissa_X;
|
||||||
|
exponent_XI <= exponent_X;
|
||||||
// REGISTER/CYCLE 10
|
|
||||||
// Exponential table
|
|
||||||
// Main sine table body
|
|
||||||
always @(*) begin
|
|
||||||
//eta <= explut_jt51[ totalatten_X[5:1] ];
|
|
||||||
// 2-bit row chooser
|
|
||||||
case( totalatten_X[7:6] )
|
|
||||||
2'b00: begin
|
|
||||||
etf <= { 1'b1, exp_X[44:36] };
|
|
||||||
etg <= { 1'b1, exp_X[35:34] };
|
|
||||||
end
|
|
||||||
2'b01: begin
|
|
||||||
etf <= exp_X[33:24];
|
|
||||||
etg <= { 2'b10, exp_X[23] };
|
|
||||||
end
|
|
||||||
2'b10: begin
|
|
||||||
etf <= { 1'b0, exp_X[22:14] };
|
|
||||||
etg <= exp_X[13:11];
|
|
||||||
end
|
|
||||||
2'b11: begin
|
|
||||||
etf <= { 2'b00, exp_X[10:3] };
|
|
||||||
etg <= exp_X[2:0];
|
|
||||||
end
|
|
||||||
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
//RESULT
|
|
||||||
mantissa_XI <= etf + ( totalatten_X[0] ? 3'd0 : etg ); //carry-out discarded
|
|
||||||
exponent_XI <= totalatten_X[11:8];
|
|
||||||
signbit_XI <= signbit_X;
|
signbit_XI <= signbit_X;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -285,30 +247,31 @@ end
|
|||||||
always @(*) begin
|
always @(*) begin
|
||||||
// Floating-point to integer, and incorporating sign bit
|
// Floating-point to integer, and incorporating sign bit
|
||||||
// Two-stage shifting of mantissa_XI by exponent_XI
|
// Two-stage shifting of mantissa_XI by exponent_XI
|
||||||
shifter <= { 3'b001, mantissa_XI };
|
shifter = { 3'b001, mantissa_XI };
|
||||||
case( ~exponent_XI[1:0] )
|
case( ~exponent_XI[1:0] )
|
||||||
2'b00: shifter_2 <= { 1'b0, shifter[12:1] }; // LSB discarded
|
2'b00: shifter_2 = { 1'b0, shifter[12:1] }; // LSB discarded
|
||||||
2'b01: shifter_2 <= shifter;
|
2'b01: shifter_2 = shifter;
|
||||||
2'b10: shifter_2 <= { shifter[11:0], 1'b0 };
|
2'b10: shifter_2 = { shifter[11:0], 1'b0 };
|
||||||
2'b11: shifter_2 <= { shifter[10:0], 2'b0 };
|
2'b11: shifter_2 = { shifter[10:0], 2'b0 };
|
||||||
endcase
|
endcase
|
||||||
case( ~exponent_XI[3:2] )
|
case( ~exponent_XI[3:2] )
|
||||||
2'b00: shifter_3 <= {12'b0, shifter_2[12] };
|
2'b00: shifter_3 = {12'b0, shifter_2[12] };
|
||||||
2'b01: shifter_3 <= { 8'b0, shifter_2[12:8] };
|
2'b01: shifter_3 = { 8'b0, shifter_2[12:8] };
|
||||||
2'b10: shifter_3 <= { 4'b0, shifter_2[12:4] };
|
2'b10: shifter_3 = { 4'b0, shifter_2[12:4] };
|
||||||
2'b11: shifter_3 <= shifter_2;
|
2'b11: shifter_3 = shifter_2;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if( clk_en ) begin
|
||||||
// REGISTER CYCLE 11
|
// REGISTER CYCLE 11
|
||||||
op_XII <= ({ test_214, shifter_3 } ^ {14{signbit_XI}}) + signbit_XI;
|
op_XII <= ({ test_214, shifter_3 } ^ {14{signbit_XI}}) + {13'd0,signbit_XI};
|
||||||
// REGISTER CYCLE 12
|
// REGISTER CYCLE 12
|
||||||
// Extra register, take output after here
|
// Extra register, take output after here
|
||||||
op_result_internal <= op_XII;
|
op_result_internal <= op_XII;
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef SIMULATION
|
`ifdef SIMULATION
|
||||||
|
/* verilator lint_off PINMISSING */
|
||||||
reg [4:0] sep24_cnt;
|
reg [4:0] sep24_cnt;
|
||||||
|
|
||||||
wire signed [13:0] op_ch0s1, op_ch1s1, op_ch2s1, op_ch3s1,
|
wire signed [13:0] op_ch0s1, op_ch1s1, op_ch2s1, op_ch3s1,
|
||||||
@ -318,14 +281,16 @@ wire signed [13:0] op_ch0s1, op_ch1s1, op_ch2s1, op_ch3s1,
|
|||||||
op_ch4s3, op_ch5s3, op_ch0s4, op_ch1s4,
|
op_ch4s3, op_ch5s3, op_ch0s4, op_ch1s4,
|
||||||
op_ch2s4, op_ch3s4, op_ch4s4, op_ch5s4;
|
op_ch2s4, op_ch3s4, op_ch4s4, op_ch5s4;
|
||||||
|
|
||||||
always @(posedge clk )
|
always @(posedge clk ) if( clk_en ) begin
|
||||||
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
||||||
|
end
|
||||||
|
|
||||||
sep24 #( .width(14), .pos0(13)) opsep
|
sep24 #( .width(14), .pos0(13)) opsep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( op_result_internal ),
|
.mixed ( op_result_internal ),
|
||||||
.mask ( 0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (op_ch0s1),
|
.ch0s1 (op_ch0s1),
|
||||||
@ -367,8 +332,9 @@ wire signed [8:0] acc_ch0s1, acc_ch1s1, acc_ch2s1, acc_ch3s1,
|
|||||||
sep24 #( .width(9), .pos0(13)) accsep
|
sep24 #( .width(9), .pos0(13)) accsep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( op_result_internal[13:5] ),
|
.mixed ( op_result_internal[13:5] ),
|
||||||
.mask ( 0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (acc_ch0s1),
|
.ch0s1 (acc_ch0s1),
|
||||||
@ -411,8 +377,9 @@ wire signed [9:0] pm_ch0s1, pm_ch1s1, pm_ch2s1, pm_ch3s1,
|
|||||||
sep24 #( .width(10), .pos0( 18 ) ) pmsep
|
sep24 #( .width(10), .pos0( 18 ) ) pmsep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( phasemod_VIII ),
|
.mixed ( phasemod_VIII ),
|
||||||
.mask ( 0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (pm_ch0s1),
|
.ch0s1 (pm_ch0s1),
|
||||||
@ -455,8 +422,9 @@ wire [9:0] phase_ch0s1, phase_ch1s1, phase_ch2s1, phase_ch3s1,
|
|||||||
sep24 #( .width(10), .pos0( 18 ) ) phsep
|
sep24 #( .width(10), .pos0( 18 ) ) phsep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( phase ),
|
.mixed ( phase ),
|
||||||
.mask ( 0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (phase_ch0s1),
|
.ch0s1 (phase_ch0s1),
|
||||||
@ -497,8 +465,9 @@ wire [9:0] eg_ch0s1, eg_ch1s1, eg_ch2s1, eg_ch3s1, eg_ch4s1, eg_ch5s1,
|
|||||||
sep24 #( .width(10), .pos0(17) ) egsep
|
sep24 #( .width(10), .pos0(17) ) egsep
|
||||||
(
|
(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.mixed ( eg_atten_IX ),
|
.mixed ( eg_atten_IX ),
|
||||||
.mask ( 0 ),
|
.mask ( 24'd0 ),
|
||||||
.cnt ( sep24_cnt ),
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
.ch0s1 (eg_ch0s1),
|
.ch0s1 (eg_ch0s1),
|
||||||
@ -529,7 +498,7 @@ sep24 #( .width(10), .pos0(17) ) egsep
|
|||||||
.ch4s4 (eg_ch4s4),
|
.ch4s4 (eg_ch4s4),
|
||||||
.ch5s4 (eg_ch5s4)
|
.ch5s4 (eg_ch5s4)
|
||||||
);
|
);
|
||||||
|
/* verilator lint_on PINMISSING */
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of JT12.
|
|
||||||
|
|
||||||
|
|
||||||
JT12 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.
|
|
||||||
|
|
||||||
JT12 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 JT12. 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: 27-1-2017
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
module jt12_opram
|
|
||||||
(
|
|
||||||
input [4:0] wr_addr,
|
|
||||||
input [4:0] rd_addr,
|
|
||||||
input clk,
|
|
||||||
input [43:0] data,
|
|
||||||
output reg [43:0] q
|
|
||||||
);
|
|
||||||
|
|
||||||
reg [43:0] ram[31:0];
|
|
||||||
initial
|
|
||||||
begin
|
|
||||||
ram[0] = { ~7'd0, 37'd0 };
|
|
||||||
ram[1] = { ~7'd0, 37'd0 };
|
|
||||||
ram[2] = { ~7'd0, 37'd0 };
|
|
||||||
ram[3] = { ~7'd0, 37'd0 };
|
|
||||||
ram[4] = { ~7'd0, 37'd0 };
|
|
||||||
ram[5] = { ~7'd0, 37'd0 };
|
|
||||||
ram[6] = { ~7'd0, 37'd0 };
|
|
||||||
ram[7] = { ~7'd0, 37'd0 };
|
|
||||||
ram[8] = { ~7'd0, 37'd0 };
|
|
||||||
ram[9] = { ~7'd0, 37'd0 };
|
|
||||||
ram[10] = { ~7'd0, 37'd0 };
|
|
||||||
ram[11] = { ~7'd0, 37'd0 };
|
|
||||||
ram[12] = { ~7'd0, 37'd0 };
|
|
||||||
ram[13] = { ~7'd0, 37'd0 };
|
|
||||||
ram[14] = { ~7'd0, 37'd0 };
|
|
||||||
ram[15] = { ~7'd0, 37'd0 };
|
|
||||||
ram[16] = { ~7'd0, 37'd0 };
|
|
||||||
ram[17] = { ~7'd0, 37'd0 };
|
|
||||||
ram[18] = { ~7'd0, 37'd0 };
|
|
||||||
ram[19] = { ~7'd0, 37'd0 };
|
|
||||||
ram[20] = { ~7'd0, 37'd0 };
|
|
||||||
ram[21] = { ~7'd0, 37'd0 };
|
|
||||||
ram[22] = { ~7'd0, 37'd0 };
|
|
||||||
ram[23] = { ~7'd0, 37'd0 };
|
|
||||||
ram[24] = { ~7'd0, 37'd0 };
|
|
||||||
ram[25] = { ~7'd0, 37'd0 };
|
|
||||||
ram[26] = { ~7'd0, 37'd0 };
|
|
||||||
ram[27] = { ~7'd0, 37'd0 };
|
|
||||||
ram[28] = { ~7'd0, 37'd0 };
|
|
||||||
ram[29] = { ~7'd0, 37'd0 };
|
|
||||||
ram[30] = { ~7'd0, 37'd0 };
|
|
||||||
ram[31] = { ~7'd0, 37'd0 };
|
|
||||||
end
|
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
|
||||||
q <= ram[rd_addr];
|
|
||||||
ram[wr_addr] <= data;
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
109
rtl/sound/jt12/jt12_pcm.v
Normal file
109
rtl/sound/jt12/jt12_pcm.v
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
module jt12_pcm(
|
||||||
|
input rst,
|
||||||
|
input clk,
|
||||||
|
(* direct_enable *) input clk_en,
|
||||||
|
input zero,
|
||||||
|
input signed [8:0] pcm,
|
||||||
|
input pcm_wr,
|
||||||
|
output reg signed [8:0] pcm_resampled
|
||||||
|
);
|
||||||
|
|
||||||
|
// reg [2:0] ratesel;
|
||||||
|
// reg [3:0] cnt8;
|
||||||
|
// reg wrcnt, wrclr;
|
||||||
|
reg last_zero;
|
||||||
|
wire zero_edge = !last_zero && zero;
|
||||||
|
/*
|
||||||
|
always @(posedge clk)
|
||||||
|
if(rst) begin
|
||||||
|
cnt8 <= 4'd0;
|
||||||
|
wrclr <= 1'd0;
|
||||||
|
ratesel <= 3'd1;
|
||||||
|
wrcnt <= 1'b0;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
if( pcm_wr ) begin
|
||||||
|
if( wrcnt ) begin
|
||||||
|
// case( cnt8[3:2] )
|
||||||
|
// 2'd3: ratesel <= 3'b111; // x8
|
||||||
|
// 2'd2: ratesel <= 3'b011; // x4
|
||||||
|
// 2'd1: ratesel <= 3'b001; // x2
|
||||||
|
// 2'd0: ratesel <= 3'b000; // x1
|
||||||
|
// endcase
|
||||||
|
cnt8 <= 4'd0;
|
||||||
|
wrcnt <= 1'b0;
|
||||||
|
end
|
||||||
|
else wrcnt <= 1'b1;
|
||||||
|
end else
|
||||||
|
if( cnt8!=4'hf && zero ) cnt8 <= cnt8 + 4'd1;
|
||||||
|
end
|
||||||
|
*/
|
||||||
|
// up-rate PCM samples
|
||||||
|
reg rate1, rate2; //, rate4, rate8;
|
||||||
|
reg cen1, cen2; //, cen4, cen8;
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if(rst)
|
||||||
|
rate2 <= 1'b0;
|
||||||
|
else begin
|
||||||
|
last_zero <= zero;
|
||||||
|
rate1 <= zero_edge;
|
||||||
|
if(zero_edge) begin
|
||||||
|
rate2 <= ~rate2;
|
||||||
|
// if(rate2) begin
|
||||||
|
// rate4 <= ~rate4;
|
||||||
|
// if(rate4) rate8<=~rate8;
|
||||||
|
// end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(negedge clk) begin
|
||||||
|
cen1 <= rate1;
|
||||||
|
cen2 <= rate1 && rate2;
|
||||||
|
// cen4 <= rate1 && rate2 && rate4;
|
||||||
|
// cen8 <= rate1 && rate2 && rate4 && rate8;
|
||||||
|
end
|
||||||
|
|
||||||
|
wire signed [8:0] pcm3; //,pcm2, pcm1;
|
||||||
|
|
||||||
|
//always @(posedge clk) if( clk_en )
|
||||||
|
// pcm_resampled <= ratesel[0] ? pcm3 : pcm;
|
||||||
|
always @(*)
|
||||||
|
pcm_resampled = pcm3;
|
||||||
|
|
||||||
|
// rate x2
|
||||||
|
//wire signed [8:0] pcm_in2 = ratesel[1] ? pcm2 : pcm;
|
||||||
|
jt12_interpol #(.calcw(10),.inw(9),.rate(2),.m(1),.n(2))
|
||||||
|
u_uprate_3(
|
||||||
|
.clk ( clk ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.cen_in ( cen2 ),
|
||||||
|
.cen_out( cen1 ),
|
||||||
|
// .snd_in ( pcm_in2 ),
|
||||||
|
.snd_in ( pcm ),
|
||||||
|
.snd_out( pcm3 )
|
||||||
|
);
|
||||||
|
/*
|
||||||
|
// rate x2
|
||||||
|
wire signed [8:0] pcm_in1 = ratesel[2] ? pcm1 : pcm;
|
||||||
|
jt12_interpol #(.calcw(10),.inw(9),.rate(2),.m(1),.n(2))
|
||||||
|
u_uprate_2(
|
||||||
|
.clk ( clk ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.cen_in ( cen4 ),
|
||||||
|
.cen_out( cen2 ),
|
||||||
|
.snd_in ( pcm_in1 ),
|
||||||
|
.snd_out( pcm2 )
|
||||||
|
);
|
||||||
|
|
||||||
|
// rate x2
|
||||||
|
jt12_interpol #(.calcw(10),.inw(9),.rate(2),.m(1),.n(2))
|
||||||
|
u_uprate_1(
|
||||||
|
.clk ( clk ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.cen_in ( cen8 ),
|
||||||
|
.cen_out( cen4 ),
|
||||||
|
.snd_in ( pcm ),
|
||||||
|
.snd_out( pcm1 )
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
endmodule // jt12_pcm
|
@ -34,379 +34,81 @@ http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc
|
|||||||
|
|
||||||
module jt12_pg(
|
module jt12_pg(
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input rst,
|
input rst,
|
||||||
// Channel frequency
|
// Channel frequency
|
||||||
input [10:0] fnum_I,
|
input [10:0] fnum_I,
|
||||||
input [ 2:0] block_I,
|
input [ 2:0] block_I,
|
||||||
// Operator multiplying
|
// Operator multiplying
|
||||||
input [ 3:0] mul_V,
|
input [ 3:0] mul_II,
|
||||||
// Operator detuning
|
// Operator detuning
|
||||||
input [ 2:0] dt1_II, // same as JT51's DT1
|
input [ 2:0] dt1_I, // same as JT51's DT1
|
||||||
// phase modulation from LFO
|
// phase modulation from LFO
|
||||||
//input [ 7:0] pm,
|
input [ 6:0] lfo_mod,
|
||||||
//input [ 2:0] pms,
|
input [ 2:0] pms_I,
|
||||||
// phase operation
|
// phase operation
|
||||||
input pg_rst_III,
|
input pg_rst_II,
|
||||||
input zero,
|
input pg_stop, // not implemented
|
||||||
input pg_stop,
|
|
||||||
|
|
||||||
output reg [ 4:0] keycode_III,
|
output reg [ 4:0] keycode_II,
|
||||||
output reg [ 9:0] phase_VIII
|
output [ 9:0] phase_VIII
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
parameter num_ch=6;
|
||||||
reg signed [8:0] mod;
|
|
||||||
|
|
||||||
always @(*) begin
|
wire [4:0] keycode_I;
|
||||||
case( pms ) // comprobar en silicio
|
wire signed [5:0] detune_mod_I;
|
||||||
3'd0: mod <= 9'd0;
|
reg signed [5:0] detune_mod_II;
|
||||||
3'd1: mod <= { 7'd0, pm[6:5] };
|
wire [16:0] phinc_I;
|
||||||
3'd2: mod <= { 6'd0, pm[6:4] };
|
|
||||||
3'd3: mod <= { 5'd0, pm[6:3] };
|
|
||||||
3'd4: mod <= { 4'd0, pm[6:2] };
|
|
||||||
3'd5: mod <= { 3'd0, pm[6:1] };
|
|
||||||
3'd6: mod <= { 1'd0, pm[6:0], 1'b0 };
|
|
||||||
3'd7: mod <= { pm[6:0], 2'b0 };
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
jt12_pm u_pm(
|
|
||||||
// Channel frequency
|
|
||||||
.kc(kc),
|
|
||||||
.kf(kf),
|
|
||||||
.add(~pm[7]),
|
|
||||||
.mod(mod),
|
|
||||||
.kcex(keycode_I)
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
wire pg_rst_VI;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// I
|
|
||||||
reg [4:0] keycode_II;
|
|
||||||
reg [16:0] phinc_II;
|
reg [16:0] phinc_II;
|
||||||
|
wire [19:0] phase_drop, phase_in;
|
||||||
|
wire [ 9:0] phase_II;
|
||||||
|
|
||||||
always @(posedge clk) begin : phase_calculation_I
|
always @(posedge clk) if(clk_en) begin
|
||||||
case ( block_I )
|
keycode_II <= keycode_I;
|
||||||
3'd0: phinc_II <= { 7'd0, fnum_I[10:1] };
|
detune_mod_II <= detune_mod_I;
|
||||||
3'd1: phinc_II <= { 6'd0, fnum_I };
|
phinc_II <= phinc_I;
|
||||||
3'd2: phinc_II <= { 5'd0, fnum_I, 1'd0 };
|
|
||||||
3'd3: phinc_II <= { 4'd0, fnum_I, 2'd0 };
|
|
||||||
3'd4: phinc_II <= { 3'd0, fnum_I, 3'd0 };
|
|
||||||
3'd5: phinc_II <= { 2'd0, fnum_I, 4'd0 };
|
|
||||||
3'd6: phinc_II <= { 1'd0, fnum_I, 5'd0 };
|
|
||||||
3'd7: phinc_II <= { fnum_I, 6'd0 };
|
|
||||||
endcase
|
|
||||||
keycode_II <= { block_I, fnum_I[10], fnum_I[10] ? (|fnum_I[9:7]) : (&fnum_I[9:7])};
|
|
||||||
end
|
end
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
jt12_pg_comb u_comb(
|
||||||
// II
|
.block ( block_I ),
|
||||||
reg [ 5:0] dt1_kf_III;
|
.fnum ( fnum_I ),
|
||||||
reg [16:0] phinc_III;
|
// Phase Modulation
|
||||||
reg [ 2:0] dt1_III;
|
.lfo_mod ( lfo_mod[6:2] ),
|
||||||
|
.pms ( pms_I ),
|
||||||
|
|
||||||
always @(posedge clk) begin : phase_calculation_II
|
// Detune
|
||||||
case( dt1_II[1:0] )
|
.detune ( dt1_I ),
|
||||||
2'd1: dt1_kf_III <= { 1'b0, keycode_II } - 6'd4;
|
.keycode ( keycode_I ),
|
||||||
2'd2: dt1_kf_III <= { 1'b0, keycode_II } + 6'd4;
|
.detune_out ( detune_mod_I ),
|
||||||
2'd3: dt1_kf_III <= { 1'b0, keycode_II } + 6'd8;
|
// Phase increment
|
||||||
default:dt1_kf_III <= { 1'b0, keycode_II };
|
.phinc_out ( phinc_I ),
|
||||||
endcase
|
// Phase add
|
||||||
dt1_III <= dt1_II;
|
.mul ( mul_II ),
|
||||||
phinc_III <= phinc_II;
|
.phase_in ( phase_drop ),
|
||||||
keycode_III <= keycode_II;
|
.pg_rst ( pg_rst_II ),
|
||||||
end
|
.detune_in ( detune_mod_II ),
|
||||||
|
.phinc_in ( phinc_II ),
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
.phase_out ( phase_in ),
|
||||||
// III
|
.phase_op ( phase_II )
|
||||||
reg [16:0] phinc_IV;
|
);
|
||||||
reg [ 4:0] pow2;
|
|
||||||
reg [ 2:0] dt1_IV;
|
|
||||||
|
|
||||||
always @(*) begin : calcpow2
|
jt12_sh_rst #( .width(20), .stages(4*num_ch) ) u_phsh(
|
||||||
case( dt1_kf_III[2:0] )
|
|
||||||
3'd0: pow2 <= 5'd16;
|
|
||||||
3'd1: pow2 <= 5'd17;
|
|
||||||
3'd2: pow2 <= 5'd19;
|
|
||||||
3'd3: pow2 <= 5'd20;
|
|
||||||
3'd4: pow2 <= 5'd22;
|
|
||||||
3'd5: pow2 <= 5'd24;
|
|
||||||
3'd6: pow2 <= 5'd26;
|
|
||||||
3'd7: pow2 <= 5'd29;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
reg [5:0] dt1_unlimited;
|
|
||||||
reg [4:0] dt1_limit, dt1_offset_IV;
|
|
||||||
|
|
||||||
always @(*) begin : dt1_limit_mux
|
|
||||||
case( dt1_III[1:0] )
|
|
||||||
default: dt1_limit <= 5'd8;
|
|
||||||
2'd1: dt1_limit <= 5'd8;
|
|
||||||
2'd2: dt1_limit <= 5'd16;
|
|
||||||
2'd3: dt1_limit <= 5'd22;
|
|
||||||
endcase
|
|
||||||
case( dt1_kf_III[5:3] )
|
|
||||||
3'd0: dt1_unlimited <= { 5'd0, pow2[4] }; // <2
|
|
||||||
3'd1: dt1_unlimited <= { 4'd0, pow2[4:3] }; // <4
|
|
||||||
3'd2: dt1_unlimited <= { 3'd0, pow2[4:2] }; // <8
|
|
||||||
3'd3: dt1_unlimited <= { 2'd0, pow2[4:1] };
|
|
||||||
3'd4: dt1_unlimited <= { 1'd0, pow2[4:0] };
|
|
||||||
3'd5: dt1_unlimited <= { pow2[4:0], 1'd0 };
|
|
||||||
default:dt1_unlimited <= 6'd0;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin : phase_calculation_III
|
|
||||||
dt1_offset_IV <= dt1_unlimited > dt1_limit ?
|
|
||||||
dt1_limit : dt1_unlimited[4:0];
|
|
||||||
dt1_IV <= dt1_III;
|
|
||||||
phinc_IV <= phinc_III;
|
|
||||||
end
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// IV
|
|
||||||
reg [16:0] phinc_V;
|
|
||||||
|
|
||||||
always @(posedge clk) begin : phase_calculation_IV
|
|
||||||
if( dt1_IV[1:0]==2'd0 )
|
|
||||||
phinc_V <= phinc_IV;
|
|
||||||
else begin
|
|
||||||
if( !dt1_IV[2] )
|
|
||||||
phinc_V <= phinc_IV + dt1_offset_IV;
|
|
||||||
else
|
|
||||||
phinc_V <= phinc_IV - dt1_offset_IV;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// V APPLY_MUL
|
|
||||||
reg [16:0] phinc_VI;
|
|
||||||
always @(posedge clk) begin : phase_calculation_V
|
|
||||||
if( mul_V==4'd0 )
|
|
||||||
phinc_VI <= { 1'b0, phinc_V[16:1] };
|
|
||||||
else
|
|
||||||
phinc_VI <= phinc_V * mul_V;
|
|
||||||
end
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// VI add phinc to the phase
|
|
||||||
wire keyon_VI;
|
|
||||||
wire [19:0] phase_drop;
|
|
||||||
reg [19:0] phase_in;
|
|
||||||
reg [ 9:0] phase_VII;
|
|
||||||
|
|
||||||
always @(*)
|
|
||||||
phase_in <= pg_rst_VI ? 20'd0 :
|
|
||||||
( pg_stop ? phase_drop : phase_drop + phinc_VI);
|
|
||||||
|
|
||||||
always @(posedge clk) begin : phase_calculation_VI
|
|
||||||
phase_VII <= phase_in[19:10];
|
|
||||||
end
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// VIII padding
|
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
phase_VIII <= phase_VII;
|
|
||||||
|
|
||||||
jt12_sh #( .width(20), .stages(24) ) u_phsh(
|
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
// .rst ( rst ),
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
.din ( phase_in ),
|
.din ( phase_in ),
|
||||||
.drop ( phase_drop)
|
.drop ( phase_drop)
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_sh #( .width(1), .stages(3) ) u_rstsh(
|
jt12_sh_rst #( .width(10), .stages(6) ) u_pad(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.din ( pg_rst_III),
|
.clk_en ( clk_en ),
|
||||||
.drop ( pg_rst_VI )
|
.rst ( rst ),
|
||||||
|
.din ( phase_II ),
|
||||||
|
.drop ( phase_VIII)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
`ifdef SIMULATION
|
|
||||||
reg [4:0] sep24_cnt;
|
|
||||||
|
|
||||||
wire [9:0] pg_ch0s1, pg_ch1s1, pg_ch2s1, pg_ch3s1,
|
|
||||||
pg_ch4s1, pg_ch5s1, pg_ch0s2, pg_ch1s2,
|
|
||||||
pg_ch2s2, pg_ch3s2, pg_ch4s2, pg_ch5s2,
|
|
||||||
pg_ch0s3, pg_ch1s3, pg_ch2s3, pg_ch3s3,
|
|
||||||
pg_ch4s3, pg_ch5s3, pg_ch0s4, pg_ch1s4,
|
|
||||||
pg_ch2s4, pg_ch3s4, pg_ch4s4, pg_ch5s4;
|
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
|
||||||
|
|
||||||
sep24 #( .width(10), .pos0(18)) stsep
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.mixed ( phase_VIII),
|
|
||||||
.mask ( 0 ),
|
|
||||||
.cnt ( sep24_cnt ),
|
|
||||||
|
|
||||||
.ch0s1 (pg_ch0s1),
|
|
||||||
.ch1s1 (pg_ch1s1),
|
|
||||||
.ch2s1 (pg_ch2s1),
|
|
||||||
.ch3s1 (pg_ch3s1),
|
|
||||||
.ch4s1 (pg_ch4s1),
|
|
||||||
.ch5s1 (pg_ch5s1),
|
|
||||||
|
|
||||||
.ch0s2 (pg_ch0s2),
|
|
||||||
.ch1s2 (pg_ch1s2),
|
|
||||||
.ch2s2 (pg_ch2s2),
|
|
||||||
.ch3s2 (pg_ch3s2),
|
|
||||||
.ch4s2 (pg_ch4s2),
|
|
||||||
.ch5s2 (pg_ch5s2),
|
|
||||||
|
|
||||||
.ch0s3 (pg_ch0s3),
|
|
||||||
.ch1s3 (pg_ch1s3),
|
|
||||||
.ch2s3 (pg_ch2s3),
|
|
||||||
.ch3s3 (pg_ch3s3),
|
|
||||||
.ch4s3 (pg_ch4s3),
|
|
||||||
.ch5s3 (pg_ch5s3),
|
|
||||||
|
|
||||||
.ch0s4 (pg_ch0s4),
|
|
||||||
.ch1s4 (pg_ch1s4),
|
|
||||||
.ch2s4 (pg_ch2s4),
|
|
||||||
.ch3s4 (pg_ch3s4),
|
|
||||||
.ch4s4 (pg_ch4s4),
|
|
||||||
.ch5s4 (pg_ch5s4)
|
|
||||||
);
|
|
||||||
|
|
||||||
wire [16:0] phinc_ch0s1, phinc_ch1s1, phinc_ch2s1, phinc_ch3s1,
|
|
||||||
phinc_ch4s1, phinc_ch5s1, phinc_ch0s2, phinc_ch1s2,
|
|
||||||
phinc_ch2s2, phinc_ch3s2, phinc_ch4s2, phinc_ch5s2,
|
|
||||||
phinc_ch0s3, phinc_ch1s3, phinc_ch2s3, phinc_ch3s3,
|
|
||||||
phinc_ch4s3, phinc_ch5s3, phinc_ch0s4, phinc_ch1s4,
|
|
||||||
phinc_ch2s4, phinc_ch3s4, phinc_ch4s4, phinc_ch5s4;
|
|
||||||
|
|
||||||
sep24 #( .width(17), .pos0(3+6)) pisep
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.mixed ( phinc_VI),
|
|
||||||
.mask ( 0 ),
|
|
||||||
.cnt ( sep24_cnt ),
|
|
||||||
|
|
||||||
.ch0s1 (phinc_ch0s1),
|
|
||||||
.ch1s1 (phinc_ch1s1),
|
|
||||||
.ch2s1 (phinc_ch2s1),
|
|
||||||
.ch3s1 (phinc_ch3s1),
|
|
||||||
.ch4s1 (phinc_ch4s1),
|
|
||||||
.ch5s1 (phinc_ch5s1),
|
|
||||||
|
|
||||||
.ch0s2 (phinc_ch0s2),
|
|
||||||
.ch1s2 (phinc_ch1s2),
|
|
||||||
.ch2s2 (phinc_ch2s2),
|
|
||||||
.ch3s2 (phinc_ch3s2),
|
|
||||||
.ch4s2 (phinc_ch4s2),
|
|
||||||
.ch5s2 (phinc_ch5s2),
|
|
||||||
|
|
||||||
.ch0s3 (phinc_ch0s3),
|
|
||||||
.ch1s3 (phinc_ch1s3),
|
|
||||||
.ch2s3 (phinc_ch2s3),
|
|
||||||
.ch3s3 (phinc_ch3s3),
|
|
||||||
.ch4s3 (phinc_ch4s3),
|
|
||||||
.ch5s3 (phinc_ch5s3),
|
|
||||||
|
|
||||||
.ch0s4 (phinc_ch0s4),
|
|
||||||
.ch1s4 (phinc_ch1s4),
|
|
||||||
.ch2s4 (phinc_ch2s4),
|
|
||||||
.ch3s4 (phinc_ch3s4),
|
|
||||||
.ch4s4 (phinc_ch4s4),
|
|
||||||
.ch5s4 (phinc_ch5s4)
|
|
||||||
);
|
|
||||||
|
|
||||||
wire [10:0] fnum_ch0s1, fnum_ch1s1, fnum_ch2s1, fnum_ch3s1,
|
|
||||||
fnum_ch4s1, fnum_ch5s1, fnum_ch0s2, fnum_ch1s2,
|
|
||||||
fnum_ch2s2, fnum_ch3s2, fnum_ch4s2, fnum_ch5s2,
|
|
||||||
fnum_ch0s3, fnum_ch1s3, fnum_ch2s3, fnum_ch3s3,
|
|
||||||
fnum_ch4s3, fnum_ch5s3, fnum_ch0s4, fnum_ch1s4,
|
|
||||||
fnum_ch2s4, fnum_ch3s4, fnum_ch4s4, fnum_ch5s4;
|
|
||||||
|
|
||||||
sep24 #( .width(11), .pos0(3+1)) fnsep
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.mixed ( fnum_I),
|
|
||||||
.mask ( 0 ),
|
|
||||||
.cnt ( sep24_cnt ),
|
|
||||||
|
|
||||||
.ch0s1 (fnum_ch0s1),
|
|
||||||
.ch1s1 (fnum_ch1s1),
|
|
||||||
.ch2s1 (fnum_ch2s1),
|
|
||||||
.ch3s1 (fnum_ch3s1),
|
|
||||||
.ch4s1 (fnum_ch4s1),
|
|
||||||
.ch5s1 (fnum_ch5s1),
|
|
||||||
|
|
||||||
.ch0s2 (fnum_ch0s2),
|
|
||||||
.ch1s2 (fnum_ch1s2),
|
|
||||||
.ch2s2 (fnum_ch2s2),
|
|
||||||
.ch3s2 (fnum_ch3s2),
|
|
||||||
.ch4s2 (fnum_ch4s2),
|
|
||||||
.ch5s2 (fnum_ch5s2),
|
|
||||||
|
|
||||||
.ch0s3 (fnum_ch0s3),
|
|
||||||
.ch1s3 (fnum_ch1s3),
|
|
||||||
.ch2s3 (fnum_ch2s3),
|
|
||||||
.ch3s3 (fnum_ch3s3),
|
|
||||||
.ch4s3 (fnum_ch4s3),
|
|
||||||
.ch5s3 (fnum_ch5s3),
|
|
||||||
|
|
||||||
.ch0s4 (fnum_ch0s4),
|
|
||||||
.ch1s4 (fnum_ch1s4),
|
|
||||||
.ch2s4 (fnum_ch2s4),
|
|
||||||
.ch3s4 (fnum_ch3s4),
|
|
||||||
.ch4s4 (fnum_ch4s4),
|
|
||||||
.ch5s4 (fnum_ch5s4)
|
|
||||||
);
|
|
||||||
|
|
||||||
wire pgrst_III_ch0s1, pgrst_III_ch1s1, pgrst_III_ch2s1, pgrst_III_ch3s1,
|
|
||||||
pgrst_III_ch4s1, pgrst_III_ch5s1, pgrst_III_ch0s2, pgrst_III_ch1s2,
|
|
||||||
pgrst_III_ch2s2, pgrst_III_ch3s2, pgrst_III_ch4s2, pgrst_III_ch5s2,
|
|
||||||
pgrst_III_ch0s3, pgrst_III_ch1s3, pgrst_III_ch2s3, pgrst_III_ch3s3,
|
|
||||||
pgrst_III_ch4s3, pgrst_III_ch5s3, pgrst_III_ch0s4, pgrst_III_ch1s4,
|
|
||||||
pgrst_III_ch2s4, pgrst_III_ch3s4, pgrst_III_ch4s4, pgrst_III_ch5s4;
|
|
||||||
|
|
||||||
sep24 #( .width(1), .pos0(23)) pgrstsep
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.mixed ( pg_rst_III),
|
|
||||||
.mask ( 0 ),
|
|
||||||
.cnt ( sep24_cnt ),
|
|
||||||
|
|
||||||
.ch0s1 (pgrst_III_ch0s1),
|
|
||||||
.ch1s1 (pgrst_III_ch1s1),
|
|
||||||
.ch2s1 (pgrst_III_ch2s1),
|
|
||||||
.ch3s1 (pgrst_III_ch3s1),
|
|
||||||
.ch4s1 (pgrst_III_ch4s1),
|
|
||||||
.ch5s1 (pgrst_III_ch5s1),
|
|
||||||
|
|
||||||
.ch0s2 (pgrst_III_ch0s2),
|
|
||||||
.ch1s2 (pgrst_III_ch1s2),
|
|
||||||
.ch2s2 (pgrst_III_ch2s2),
|
|
||||||
.ch3s2 (pgrst_III_ch3s2),
|
|
||||||
.ch4s2 (pgrst_III_ch4s2),
|
|
||||||
.ch5s2 (pgrst_III_ch5s2),
|
|
||||||
|
|
||||||
.ch0s3 (pgrst_III_ch0s3),
|
|
||||||
.ch1s3 (pgrst_III_ch1s3),
|
|
||||||
.ch2s3 (pgrst_III_ch2s3),
|
|
||||||
.ch3s3 (pgrst_III_ch3s3),
|
|
||||||
.ch4s3 (pgrst_III_ch4s3),
|
|
||||||
.ch5s3 (pgrst_III_ch5s3),
|
|
||||||
|
|
||||||
.ch0s4 (pgrst_III_ch0s4),
|
|
||||||
.ch1s4 (pgrst_III_ch1s4),
|
|
||||||
.ch2s4 (pgrst_III_ch2s4),
|
|
||||||
.ch3s4 (pgrst_III_ch3s4),
|
|
||||||
.ch4s4 (pgrst_III_ch4s4),
|
|
||||||
.ch5s4 (pgrst_III_ch5s4)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
`endif
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
90
rtl/sound/jt12/jt12_pg_comb.v
Normal file
90
rtl/sound/jt12/jt12_pg_comb.v
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 2-11-2018
|
||||||
|
|
||||||
|
Based on information posted by Nemesis on:
|
||||||
|
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||||
|
|
||||||
|
100% compared with Alexey Khokholov (Nuke.YKT) work with identical results.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_pg_comb(
|
||||||
|
input [ 2:0] block,
|
||||||
|
input [10:0] fnum,
|
||||||
|
// Phase Modulation
|
||||||
|
input [ 4:0] lfo_mod,
|
||||||
|
input [ 2:0] pms,
|
||||||
|
// output [ 7:0] pm_out,
|
||||||
|
|
||||||
|
// Detune
|
||||||
|
input [ 2:0] detune,
|
||||||
|
|
||||||
|
output [ 4:0] keycode,
|
||||||
|
output signed [5:0] detune_out,
|
||||||
|
// Phase increment
|
||||||
|
output [16:0] phinc_out,
|
||||||
|
// Phase add
|
||||||
|
input [ 3:0] mul,
|
||||||
|
input [19:0] phase_in,
|
||||||
|
input pg_rst,
|
||||||
|
// input signed [7:0] pm_in,
|
||||||
|
input signed [5:0] detune_in,
|
||||||
|
input [16:0] phinc_in,
|
||||||
|
|
||||||
|
output [19:0] phase_out,
|
||||||
|
output [ 9:0] phase_op
|
||||||
|
);
|
||||||
|
|
||||||
|
wire signed [8:0] pm_offset;
|
||||||
|
|
||||||
|
/* pm, pg_dt and pg_inc operate in parallel */
|
||||||
|
jt12_pm u_pm(
|
||||||
|
.lfo_mod ( lfo_mod ),
|
||||||
|
.fnum ( fnum ),
|
||||||
|
.pms ( pms ),
|
||||||
|
.pm_offset ( pm_offset )
|
||||||
|
);
|
||||||
|
|
||||||
|
jt12_pg_dt u_dt(
|
||||||
|
.block ( block ),
|
||||||
|
.fnum ( fnum ),
|
||||||
|
.detune ( detune ),
|
||||||
|
.keycode ( keycode ),
|
||||||
|
.detune_signed( detune_out )
|
||||||
|
);
|
||||||
|
|
||||||
|
jt12_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
|
||||||
|
|
||||||
|
jt12_pg_sum u_sum(
|
||||||
|
.mul ( mul ),
|
||||||
|
.phase_in ( phase_in ),
|
||||||
|
.pg_rst ( pg_rst ),
|
||||||
|
.detune_signed ( detune_in ),
|
||||||
|
.phinc_pure ( phinc_in ),
|
||||||
|
.phase_out ( phase_out ),
|
||||||
|
.phase_op ( phase_op )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule // jt12_pg_comb
|
82
rtl/sound/jt12/jt12_pg_dt.v
Normal file
82
rtl/sound/jt12/jt12_pg_dt.v
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 2-11-2018
|
||||||
|
|
||||||
|
Based on information posted by Nemesis on:
|
||||||
|
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||||
|
|
||||||
|
Note that detune produces an output even for fnum==0, is that correct?
|
||||||
|
|
||||||
|
Based on jt51_phasegen.v, from JT51
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_pg_dt(
|
||||||
|
input [ 2:0] block,
|
||||||
|
input [10:0] fnum,
|
||||||
|
input [ 2:0] detune,
|
||||||
|
|
||||||
|
output reg [ 4:0] keycode,
|
||||||
|
output reg signed [5:0] detune_signed
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [5:0] detune_kf;
|
||||||
|
reg [4:0] pow2;
|
||||||
|
reg [5:0] detune_unlimited;
|
||||||
|
reg [4:0] detune_limit, detune_limited;
|
||||||
|
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
keycode = { block, fnum[10], fnum[10] ? (|fnum[9:7]) : (&fnum[9:7])};
|
||||||
|
case( detune[1:0] )
|
||||||
|
2'd1: detune_kf = { 1'b0, keycode } - 6'd4;
|
||||||
|
2'd2: detune_kf = { 1'b0, keycode } + 6'd4;
|
||||||
|
2'd3: detune_kf = { 1'b0, keycode } + 6'd8;
|
||||||
|
default:detune_kf = { 1'b0, keycode };
|
||||||
|
endcase
|
||||||
|
case( detune_kf[2:0] )
|
||||||
|
3'd0: pow2 = 5'd16;
|
||||||
|
3'd1: pow2 = 5'd17;
|
||||||
|
3'd2: pow2 = 5'd19;
|
||||||
|
3'd3: pow2 = 5'd20;
|
||||||
|
3'd4: pow2 = 5'd22;
|
||||||
|
3'd5: pow2 = 5'd24;
|
||||||
|
3'd6: pow2 = 5'd26;
|
||||||
|
3'd7: pow2 = 5'd29;
|
||||||
|
endcase
|
||||||
|
case( detune[1:0] )
|
||||||
|
2'd0: detune_limit = 5'd0;
|
||||||
|
2'd1: detune_limit = 5'd8;
|
||||||
|
2'd2: detune_limit = 5'd16;
|
||||||
|
2'd3: detune_limit = 5'd22;
|
||||||
|
endcase
|
||||||
|
case( detune_kf[5:3] )
|
||||||
|
3'd0: detune_unlimited = { 5'd0, pow2[4] }; // <2
|
||||||
|
3'd1: detune_unlimited = { 4'd0, pow2[4:3] }; // <4
|
||||||
|
3'd2: detune_unlimited = { 3'd0, pow2[4:2] }; // <8
|
||||||
|
3'd3: detune_unlimited = { 2'd0, pow2[4:1] };
|
||||||
|
3'd4: detune_unlimited = { 1'd0, pow2[4:0] };
|
||||||
|
3'd5: detune_unlimited = { pow2[4:0], 1'd0 };
|
||||||
|
default:detune_unlimited = 6'd0;
|
||||||
|
endcase
|
||||||
|
detune_limited = detune_unlimited > {1'b0, detune_limit} ?
|
||||||
|
detune_limit : detune_unlimited[4:0];
|
||||||
|
detune_signed = !detune[2] ? {1'b0,detune_limited} : (~{1'b0,detune_limited}+6'd1);
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
50
rtl/sound/jt12/jt12_pg_inc.v
Normal file
50
rtl/sound/jt12/jt12_pg_inc.v
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 2-11-2018
|
||||||
|
|
||||||
|
Based on information posted by Nemesis on:
|
||||||
|
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||||
|
|
||||||
|
Based on jt51_phasegen.v, from JT51
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_pg_inc (
|
||||||
|
input [ 2:0] block,
|
||||||
|
input [10:0] fnum,
|
||||||
|
input signed [8:0] pm_offset,
|
||||||
|
output reg [16:0] phinc_pure
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [11:0] fnum_mod;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
fnum_mod = {fnum,1'b0} + {{3{pm_offset[8]}},pm_offset};
|
||||||
|
case ( block )
|
||||||
|
3'd0: phinc_pure = { 7'd0, fnum_mod[11:2] };
|
||||||
|
3'd1: phinc_pure = { 6'd0, fnum_mod[11:1] };
|
||||||
|
3'd2: phinc_pure = { 5'd0, fnum_mod[11:0] };
|
||||||
|
3'd3: phinc_pure = { 4'd0, fnum_mod, 1'd0 };
|
||||||
|
3'd4: phinc_pure = { 3'd0, fnum_mod, 2'd0 };
|
||||||
|
3'd5: phinc_pure = { 2'd0, fnum_mod, 3'd0 };
|
||||||
|
3'd6: phinc_pure = { 1'd0, fnum_mod, 4'd0 };
|
||||||
|
3'd7: phinc_pure = { fnum_mod, 5'd0 };
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // jt12_pg_inc
|
49
rtl/sound/jt12/jt12_pg_sum.v
Normal file
49
rtl/sound/jt12/jt12_pg_sum.v
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 2-11-2018
|
||||||
|
|
||||||
|
Based on information posted by Nemesis on:
|
||||||
|
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||||
|
|
||||||
|
Based on jt51_phasegen.v, from JT51
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_pg_sum (
|
||||||
|
input [ 3:0] mul,
|
||||||
|
input [19:0] phase_in,
|
||||||
|
input pg_rst,
|
||||||
|
input signed [5:0] detune_signed,
|
||||||
|
input [16:0] phinc_pure,
|
||||||
|
|
||||||
|
output reg [19:0] phase_out,
|
||||||
|
output reg [ 9:0] phase_op
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [16:0] phinc_premul;
|
||||||
|
reg [19:0] phinc_mul;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
phinc_premul = phinc_pure + {{11{detune_signed[5]}},detune_signed};
|
||||||
|
phinc_mul = ( mul==4'd0 ) ? {4'b0,phinc_premul[16:1]} : ({3'd0,phinc_premul} * mul);
|
||||||
|
|
||||||
|
phase_out = pg_rst ? 20'd0 : (phase_in + { phinc_mul});
|
||||||
|
phase_op = phase_out[19:10];
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // jt12_pg_sum
|
@ -1,77 +0,0 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of JT12.
|
|
||||||
|
|
||||||
|
|
||||||
JT12 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.
|
|
||||||
|
|
||||||
JT12 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 JT12. 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: 27-1-2017
|
|
||||||
|
|
||||||
*/
|
|
||||||
// altera message_off 10030
|
|
||||||
|
|
||||||
module jt12_phrom
|
|
||||||
(
|
|
||||||
input [4:0] addr,
|
|
||||||
input clk,
|
|
||||||
output reg [45:0] ph
|
|
||||||
);
|
|
||||||
|
|
||||||
reg [45:0] sinetable[31:0];
|
|
||||||
initial
|
|
||||||
begin
|
|
||||||
sinetable[5'd0 ] <= 46'b0001100000100100010001000010101010101001010010;
|
|
||||||
sinetable[5'd1 ] <= 46'b0001100000110100000100000010010001001101000001;
|
|
||||||
sinetable[5'd2 ] <= 46'b0001100000110100000100110010001011001101100000;
|
|
||||||
sinetable[5'd3 ] <= 46'b0001110000010000000000110010110001001101110010;
|
|
||||||
sinetable[5'd4 ] <= 46'b0001110000010000001100000010111010001101101001;
|
|
||||||
sinetable[5'd5 ] <= 46'b0001110000010100001001100010000000101101111010;
|
|
||||||
sinetable[5'd6 ] <= 46'b0001110000010100001101100010010011001101011010;
|
|
||||||
sinetable[5'd7 ] <= 46'b0001110000011100000101010010111000101111111100;
|
|
||||||
sinetable[5'd8 ] <= 46'b0001110000111000000001110010101110001101110111;
|
|
||||||
sinetable[5'd9 ] <= 46'b0001110000111000010100111000011101011010100110;
|
|
||||||
sinetable[5'd10] <= 46'b0001110000111100011000011000111100001001111010;
|
|
||||||
sinetable[5'd11] <= 46'b0001110000111100011100111001101011001001110111;
|
|
||||||
sinetable[5'd12] <= 46'b0100100001010000010001011001001000111010110111;
|
|
||||||
sinetable[5'd13] <= 46'b0100100001010100010001001001110001111100101010;
|
|
||||||
sinetable[5'd14] <= 46'b0100100001010100010101101101111110100101000110;
|
|
||||||
sinetable[5'd15] <= 46'b0100100011100000001000011001010110101101111001;
|
|
||||||
sinetable[5'd16] <= 46'b0100100011100100001000101011100101001011101111;
|
|
||||||
sinetable[5'd17] <= 46'b0100100011101100000111011010000001011010110001;
|
|
||||||
sinetable[5'd18] <= 46'b0100110011001000000111101010000010111010111111;
|
|
||||||
sinetable[5'd19] <= 46'b0100110011001100001011011110101110110110000001;
|
|
||||||
sinetable[5'd20] <= 46'b0100110011101000011010111011001010001101110001;
|
|
||||||
sinetable[5'd21] <= 46'b0100110011101101011010110101111001010100001111;
|
|
||||||
sinetable[5'd22] <= 46'b0111000010000001010111000101010101010110010111;
|
|
||||||
sinetable[5'd23] <= 46'b0111000010000101010111110111110101010010111011;
|
|
||||||
sinetable[5'd24] <= 46'b0111000010110101101000101100001000010000011001;
|
|
||||||
sinetable[5'd25] <= 46'b0111010010011001100100011110100100010010010010;
|
|
||||||
sinetable[5'd26] <= 46'b0111010010111010100101100101000000110100100011;
|
|
||||||
sinetable[5'd27] <= 46'b1010000010011010101101011101100001110010011010;
|
|
||||||
sinetable[5'd28] <= 46'b1010000010111111111100100111010100010000111001;
|
|
||||||
sinetable[5'd29] <= 46'b1010010111110100110010001100111001010110100000;
|
|
||||||
sinetable[5'd30] <= 46'b1011010111010011111011011110000100110010100001;
|
|
||||||
sinetable[5'd31] <= 46'b1110011011110001111011100111100001110110100111;
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
always @ (posedge clk)
|
|
||||||
ph <= sinetable[addr];
|
|
||||||
|
|
||||||
endmodule
|
|
62
rtl/sound/jt12/jt12_pm.v
Normal file
62
rtl/sound/jt12/jt12_pm.v
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* This file is part of jt12.
|
||||||
|
|
||||||
|
jt12 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.
|
||||||
|
|
||||||
|
jt12 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 jt12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 14-10-2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
// altera message_off 10030
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
// This implementation follows that of Alexey Khokholov (Nuke.YKT) in C language.
|
||||||
|
|
||||||
|
module jt12_pm (
|
||||||
|
input [4:0] lfo_mod,
|
||||||
|
input [10:0] fnum,
|
||||||
|
input [2:0] pms,
|
||||||
|
output reg signed [8:0] pm_offset
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
reg [7:0] pm_unsigned;
|
||||||
|
reg [7:0] pm_base;
|
||||||
|
reg [9:0] pm_shifted;
|
||||||
|
|
||||||
|
wire [2:0] index = lfo_mod[3] ? (~lfo_mod[2:0]) : lfo_mod[2:0];
|
||||||
|
|
||||||
|
reg [3:0] lfo_sh1_lut [0:63];
|
||||||
|
reg [3:0] lfo_sh2_lut [0:63];
|
||||||
|
reg [2:0] lfo_sh1, lfo_sh2;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$readmemh("lfo_sh1_lut.hex",lfo_sh1_lut);
|
||||||
|
$readmemh("lfo_sh2_lut.hex",lfo_sh2_lut);
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
lfo_sh1 = lfo_sh1_lut[{pms,index}][2:0];
|
||||||
|
lfo_sh2 = lfo_sh2_lut[{pms,index}][2:0];
|
||||||
|
pm_base = ({1'b0,fnum[10:4]}>>lfo_sh1) + ({1'b0,fnum[10:4]}>>lfo_sh2);
|
||||||
|
case( pms )
|
||||||
|
default: pm_shifted = { 2'b0, pm_base };
|
||||||
|
3'd6: pm_shifted = { 1'b0, pm_base, 1'b0 };
|
||||||
|
3'd7: pm_shifted = { pm_base, 2'b0 };
|
||||||
|
endcase // pms
|
||||||
|
pm_offset = lfo_mod[4] ? (-{1'b0,pm_shifted[9:2]}) : {1'b0,pm_shifted[9:2]};
|
||||||
|
end // always @(*)
|
||||||
|
|
||||||
|
endmodule
|
@ -1,6 +1,3 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
|
|
||||||
/* This file is part of JT12.
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
@ -23,10 +20,10 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
module jt12_reg(
|
module jt12_reg(
|
||||||
input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input [7:0] din,
|
input [7:0] din,
|
||||||
|
|
||||||
input [2:0] ch,
|
input [2:0] ch,
|
||||||
@ -38,19 +35,17 @@ module jt12_reg(
|
|||||||
|
|
||||||
input up_keyon,
|
input up_keyon,
|
||||||
input up_alg,
|
input up_alg,
|
||||||
input up_block,
|
|
||||||
input up_fnumlo,
|
input up_fnumlo,
|
||||||
input up_pms,
|
input up_pms,
|
||||||
input up_dt1,
|
input up_dt1,
|
||||||
input up_tl,
|
input up_tl,
|
||||||
input up_ks_ar,
|
input up_ks_ar,
|
||||||
input up_amen_d1r,
|
input up_amen_dr,
|
||||||
input up_d2r,
|
input up_sr,
|
||||||
|
|
||||||
input up_d1l,
|
input up_sl_rr,
|
||||||
input up_ssgeg,
|
input up_ssgeg,
|
||||||
|
|
||||||
output busy,
|
|
||||||
output reg ch6op, // 1 when the operator belongs to CH6
|
output reg ch6op, // 1 when the operator belongs to CH6
|
||||||
|
|
||||||
// CH3 Effect-mode operation
|
// CH3 Effect-mode operation
|
||||||
@ -61,6 +56,7 @@ module jt12_reg(
|
|||||||
input [ 2:0] block_ch3op2,
|
input [ 2:0] block_ch3op2,
|
||||||
input [ 2:0] block_ch3op3,
|
input [ 2:0] block_ch3op3,
|
||||||
input [ 2:0] block_ch3op1,
|
input [ 2:0] block_ch3op1,
|
||||||
|
input [ 5:0] latch_fnum,
|
||||||
// Pipeline order
|
// Pipeline order
|
||||||
output reg zero,
|
output reg zero,
|
||||||
output s1_enters,
|
output s1_enters,
|
||||||
@ -69,11 +65,12 @@ module jt12_reg(
|
|||||||
output s4_enters,
|
output s4_enters,
|
||||||
|
|
||||||
// Operator
|
// Operator
|
||||||
output use_prevprev1,
|
output xuse_prevprev1,
|
||||||
output use_internal_x,
|
output xuse_internal,
|
||||||
output use_internal_y,
|
output yuse_internal,
|
||||||
output use_prev2,
|
output xuse_prev2,
|
||||||
output use_prev1,
|
output yuse_prev1,
|
||||||
|
output yuse_prev2,
|
||||||
|
|
||||||
// PG
|
// PG
|
||||||
output [10:0] fnum_I,
|
output [10:0] fnum_I,
|
||||||
@ -81,34 +78,49 @@ module jt12_reg(
|
|||||||
// channel configuration
|
// channel configuration
|
||||||
output [1:0] rl,
|
output [1:0] rl,
|
||||||
output reg [2:0] fb_II,
|
output reg [2:0] fb_II,
|
||||||
output [2:0] alg,
|
output [2:0] alg_I,
|
||||||
// Operator multiplying
|
// Operator multiplying
|
||||||
output [ 3:0] mul_V,
|
output [ 3:0] mul_II,
|
||||||
// Operator detuning
|
// Operator detuning
|
||||||
output [ 2:0] dt1_II,
|
output [ 2:0] dt1_I,
|
||||||
|
|
||||||
// EG
|
// EG
|
||||||
output [4:0] ar_II, // attack rate
|
output [4:0] ar_I, // attack rate
|
||||||
output [4:0] d1r_II, // decay rate
|
output [4:0] d1r_I, // decay rate
|
||||||
output [4:0] d2r_II, // sustain rate
|
output [4:0] d2r_I, // sustain rate
|
||||||
output [3:0] rr_II, // release rate
|
output [3:0] rr_I, // release rate
|
||||||
output [3:0] d1l, // sustain level
|
output [3:0] sl_I, // sustain level
|
||||||
output [1:0] ks_III, // key scale
|
output [1:0] ks_II, // key scale
|
||||||
output ssg_en_II,
|
output ssg_en_I,
|
||||||
output [2:0] ssg_eg_II,
|
output [2:0] ssg_eg_I,
|
||||||
output [6:0] tl_VII,
|
output [6:0] tl_IV,
|
||||||
output [2:0] pms,
|
output [2:0] pms_I,
|
||||||
output [1:0] ams_VII,
|
output [1:0] ams_IV,
|
||||||
output amsen_VII,
|
output amsen_IV,
|
||||||
|
|
||||||
// envelope operation
|
// envelope operation
|
||||||
output keyon_II
|
output keyon_I
|
||||||
);
|
);
|
||||||
|
|
||||||
|
parameter num_ch=6; // Use only 3 (YM2203/YM2610) or 6 (YM2612/YM2608)
|
||||||
|
|
||||||
|
|
||||||
reg [4:0] cnt;
|
|
||||||
reg [1:0] next_op, cur_op;
|
reg [1:0] next_op, cur_op;
|
||||||
reg [2:0] next_ch, cur_ch;
|
reg [2:0] next_ch, cur_ch;
|
||||||
|
reg last;
|
||||||
|
|
||||||
|
`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
|
||||||
|
// This does not work with NCVERILOG
|
||||||
|
initial begin
|
||||||
|
cur_op = 2'd0;
|
||||||
|
cur_ch = 3'd0;
|
||||||
|
last = 1'b0;
|
||||||
|
zero = 1'b1;
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
assign s1_enters = cur_op == 2'b00;
|
assign s1_enters = cur_op == 2'b00;
|
||||||
assign s3_enters = cur_op == 2'b01;
|
assign s3_enters = cur_op == 2'b01;
|
||||||
@ -120,7 +132,7 @@ wire [4:0] cur = { cur_op, cur_ch };
|
|||||||
|
|
||||||
wire [2:0] fb_I;
|
wire [2:0] fb_I;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if( clk_en ) begin
|
||||||
fb_II <= fb_I;
|
fb_II <= fb_I;
|
||||||
ch6op <= next_ch==3'd6;
|
ch6op <= next_ch==3'd6;
|
||||||
end
|
end
|
||||||
@ -149,215 +161,210 @@ wire [4:0] req_opch_I = { op, ch };
|
|||||||
wire [4:0] req_opch_II, req_opch_III,
|
wire [4:0] req_opch_II, req_opch_III,
|
||||||
req_opch_IV, req_opch_V, req_opch_VI;
|
req_opch_IV, req_opch_V, req_opch_VI;
|
||||||
|
|
||||||
jt12_sumch u_opch_II ( .chin(req_opch_I ), .chout(req_opch_II) );
|
jt12_sumch #(.num_ch(num_ch)) u_opch_II ( .chin(req_opch_I ), .chout(req_opch_II ) );
|
||||||
jt12_sumch u_opch_III( .chin(req_opch_II ), .chout(req_opch_III) );
|
jt12_sumch #(.num_ch(num_ch)) u_opch_III( .chin(req_opch_II ), .chout(req_opch_III) );
|
||||||
jt12_sumch u_opch_IV ( .chin(req_opch_III), .chout(req_opch_IV) );
|
jt12_sumch #(.num_ch(num_ch)) u_opch_IV ( .chin(req_opch_III), .chout(req_opch_IV ) );
|
||||||
jt12_sumch u_opch_V ( .chin(req_opch_IV ), .chout(req_opch_V) );
|
jt12_sumch #(.num_ch(num_ch)) u_opch_V ( .chin(req_opch_IV ), .chout(req_opch_V ) );
|
||||||
jt12_sumch u_opch_VI ( .chin(req_opch_V ), .chout(req_opch_VI) );
|
// jt12_sumch #(.num_ch(num_ch)) u_opch_VI ( .chin(req_opch_V ), .chout(req_opch_VI) );
|
||||||
|
|
||||||
wire update_op_I = cur == req_opch_I;
|
wire update_op_I = cur == req_opch_I;
|
||||||
wire update_op_II = cur == req_opch_II;
|
wire update_op_II = cur == req_opch_II;
|
||||||
wire update_op_III= cur == req_opch_III;
|
// wire update_op_III= cur == req_opch_III;
|
||||||
// wire update_op_IV = cur == opch_IV;
|
wire update_op_IV = cur == req_opch_IV;
|
||||||
wire update_op_V = cur == req_opch_V;
|
// wire update_op_V = cur == req_opch_V;
|
||||||
// wire update_op_VI = cur == opch_VI;
|
// wire update_op_VI = cur == opch_VI;
|
||||||
wire [2:0] op_plus1 = op+2'd1;
|
// wire [2:0] op_plus1 = op+2'd1;
|
||||||
wire update_op_VII= cur == { op_plus1[1:0], ch };
|
// wire update_op_VII= cur == { op_plus1[1:0], ch };
|
||||||
|
|
||||||
// key on/off
|
// key on/off
|
||||||
wire [3:0] keyon_op = din[7:4];
|
wire [3:0] keyon_op = din[7:4];
|
||||||
wire [2:0] keyon_ch = din[2:0];
|
wire [2:0] keyon_ch = din[2:0];
|
||||||
// channel data
|
// channel data
|
||||||
wire [1:0] rl_in = din[7:6];
|
//wire [1:0] rl_in = din[7:6];
|
||||||
wire [2:0] fb_in = din[5:3];
|
wire [2:0] fb_in = din[5:3];
|
||||||
wire [2:0] alg_in = din[2:0];
|
wire [2:0] alg_in = din[2:0];
|
||||||
wire [2:0] pms_in = din[2:0];
|
wire [2:0] pms_in = din[2:0];
|
||||||
wire [1:0] ams_in = din[5:4];
|
wire [1:0] ams_in = din[5:4];
|
||||||
wire [2:0] block_in= din[5:3];
|
|
||||||
wire [2:0] fnhi_in = din[2:0];
|
|
||||||
wire [7:0] fnlo_in = din;
|
wire [7:0] fnlo_in = din;
|
||||||
// operator data
|
|
||||||
wire [2:0] dt1_in = din[6:4];
|
|
||||||
wire [3:0] mul_in = din[3:0];
|
|
||||||
wire [6:0] tl_in = din[6:0];
|
|
||||||
wire [1:0] ks_in = din[7:6];
|
|
||||||
wire [4:0] ar_in = din[4:0];
|
|
||||||
wire amen_in = din[7];
|
|
||||||
wire [4:0] d1r_in = din[4:0];
|
|
||||||
wire [4:0] d2r_in = din[4:0];
|
|
||||||
wire [3:0] d1l_in = din[7:4];
|
|
||||||
wire [3:0] rr_in = din[3:0];
|
|
||||||
wire [3:0] ssg_in = din[3:0];
|
|
||||||
|
|
||||||
wire [3:0] ssg;
|
|
||||||
|
|
||||||
reg last;
|
|
||||||
|
|
||||||
wire update_ch_I = cur_ch == ch;
|
wire update_ch_I = cur_ch == ch;
|
||||||
|
wire update_ch_IV = num_ch==6 ?
|
||||||
|
{ ~cur_ch[2], cur_ch[1:0]} == ch : // 6 channels
|
||||||
|
cur[1:0] == ch[1:0]; // 3 channels
|
||||||
|
|
||||||
wire up_alg_ch = up_alg & update_ch_I;
|
wire up_alg_ch = up_alg & update_ch_I;
|
||||||
wire up_block_ch= up_block & update_ch_I;
|
|
||||||
wire up_fnumlo_ch=up_fnumlo & update_ch_I;
|
wire up_fnumlo_ch=up_fnumlo & update_ch_I;
|
||||||
wire up_pms_ch = up_pms & update_ch_I;
|
wire up_pms_ch = up_pms & update_ch_I;
|
||||||
|
wire up_ams_ch = up_pms & update_ch_IV;
|
||||||
// DT1 & MUL
|
|
||||||
wire up_dt1_op = up_dt1 & update_op_II;
|
|
||||||
wire up_mul_op = up_dt1 & update_op_V;
|
|
||||||
// TL
|
|
||||||
wire up_tl_op = up_tl & update_op_VII;
|
|
||||||
// KS & AR
|
|
||||||
wire up_ks_op = up_ks_ar & update_op_III;
|
|
||||||
wire up_ar_op = up_ks_ar & update_op_II;
|
|
||||||
// AM ON, D1R
|
|
||||||
wire up_amen_op = up_amen_d1r & update_op_VII;
|
|
||||||
wire up_d1r_op = up_amen_d1r & update_op_II;
|
|
||||||
// Sustain Rate (D2R)
|
|
||||||
wire up_d2r_op = up_d2r & update_op_II;
|
|
||||||
// D1L & RR
|
|
||||||
wire up_d1l_op = up_d1l & update_op_I;
|
|
||||||
wire up_rr_op = up_d1l & update_op_II;
|
|
||||||
// SSG
|
|
||||||
//wire up_ssgen_op = up_ssgeg & update_op_I;
|
|
||||||
wire up_ssg_op = up_ssgeg & update_op_II;
|
|
||||||
|
|
||||||
wire up = up_alg | up_block | up_fnumlo | up_pms |
|
|
||||||
up_dt1 | up_tl | up_ks_ar | up_amen_d1r |
|
|
||||||
up_d2r | up_d1l | up_ssgeg | up_keyon;
|
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
// next <= cur==5'd23 ? 5'd0 : cur +1'b1;
|
// next = cur==5'd23 ? 5'd0 : cur +1'b1;
|
||||||
next_op <= cur_ch==3'd6 ? cur_op+1'b1 : cur_op;
|
if( num_ch==6 ) begin
|
||||||
next_ch <= cur_ch[1:0]==2'b10 ? cur_ch+2'd2 : cur_ch+1'd1;
|
next_op = cur_ch==3'd6 ? cur_op+1'b1 : cur_op;
|
||||||
|
next_ch = cur_ch[1:0]==2'b10 ? cur_ch+2'd2 : cur_ch+1'd1;
|
||||||
|
end else begin // 3 channels
|
||||||
|
next_op = cur_ch==3'd2 ? cur_op+1'b1 : cur_op;
|
||||||
|
next_ch = cur_ch[1:0]==2'b10 ? 3'd0 : cur_ch+1'd1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
reg busy_op;
|
|
||||||
reg up_keyon_long;
|
|
||||||
|
|
||||||
assign busy = busy_op;
|
|
||||||
|
|
||||||
|
|
||||||
always @(posedge clk) begin : up_counter
|
always @(posedge clk) begin : up_counter
|
||||||
if( rst ) begin
|
if( clk_en ) begin
|
||||||
cnt <= 5'h0;
|
|
||||||
last <= 1'b0;
|
|
||||||
zero <= 1'b1;
|
|
||||||
busy_op <= 1'b0;
|
|
||||||
up_keyon_long <= 1'b0;
|
|
||||||
cur_op <= 2'd0;
|
|
||||||
cur_ch <= 3'd0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
{ cur_op, cur_ch } <= { next_op, next_ch };
|
{ cur_op, cur_ch } <= { next_op, next_ch };
|
||||||
zero <= next == 5'd0;
|
zero <= next == 5'd0;
|
||||||
last <= up;
|
|
||||||
if( up && !last ) begin
|
|
||||||
cnt <= cur;
|
|
||||||
busy_op <= 1'b1;
|
|
||||||
up_keyon_long <= up_keyon;
|
|
||||||
end
|
|
||||||
else if( cnt == cur ) begin
|
|
||||||
busy_op <= 1'b0;
|
|
||||||
up_keyon_long <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
jt12_kon u_kon(
|
jt12_kon #(.num_ch(num_ch)) u_kon(
|
||||||
.rst ( rst ),
|
.rst ( rst ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
.keyon_op ( keyon_op ),
|
.keyon_op ( keyon_op ),
|
||||||
.keyon_ch ( keyon_ch ),
|
.keyon_ch ( keyon_ch ),
|
||||||
.cur_op ( cur_op ),
|
.next_op ( next_op ),
|
||||||
.cur_ch ( cur_ch ),
|
.next_ch ( next_ch ),
|
||||||
.up_keyon ( up_keyon_long ),
|
.up_keyon ( up_keyon ),
|
||||||
.csm ( csm ),
|
.csm ( csm ),
|
||||||
.flag_A ( flag_A ),
|
// .flag_A ( flag_A ),
|
||||||
.overflow_A ( overflow_A),
|
.overflow_A ( overflow_A),
|
||||||
|
|
||||||
.keyon_II ( keyon_II )
|
.keyon_I ( keyon_I )
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_mod u_mod(
|
jt12_mod #(.num_ch(num_ch)) u_mod(
|
||||||
.alg_I ( alg ),
|
.alg_I ( alg_I ),
|
||||||
.s1_enters ( s1_enters ),
|
.s1_enters ( s1_enters ),
|
||||||
.s3_enters ( s3_enters ),
|
.s3_enters ( s3_enters ),
|
||||||
.s2_enters ( s2_enters ),
|
.s2_enters ( s2_enters ),
|
||||||
.s4_enters ( s4_enters ),
|
.s4_enters ( s4_enters ),
|
||||||
|
|
||||||
.use_prevprev1 ( use_prevprev1 ),
|
.xuse_prevprev1 ( xuse_prevprev1 ),
|
||||||
.use_internal_x( use_internal_x ),
|
.xuse_internal ( xuse_internal ),
|
||||||
.use_internal_y( use_internal_y ),
|
.yuse_internal ( yuse_internal ),
|
||||||
.use_prev2 ( use_prev2 ),
|
.xuse_prev2 ( xuse_prev2 ),
|
||||||
.use_prev1 ( use_prev1 )
|
.yuse_prev1 ( yuse_prev1 ),
|
||||||
|
.yuse_prev2 ( yuse_prev2 )
|
||||||
);
|
);
|
||||||
|
|
||||||
// memory for OP registers
|
wire [43:0] shift_out;
|
||||||
parameter regop_width=44;
|
|
||||||
|
|
||||||
wire [regop_width-1:0] regop_in, regop_out;
|
generate
|
||||||
|
if( num_ch==6 ) begin
|
||||||
|
// YM2612 / YM3438: Two CSR.
|
||||||
|
wire [43:0] shift_middle;
|
||||||
|
|
||||||
jt12_opram u_opram(
|
jt12_csr u_csr0(
|
||||||
|
.rst ( rst ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.wr_addr ( cur ),
|
.clk_en ( clk_en ),
|
||||||
.rd_addr ( next ),
|
.din ( din ),
|
||||||
.data ( regop_in ),
|
.shift_in ( shift_out ),
|
||||||
.q ( regop_out )
|
.shift_out ( shift_middle ),
|
||||||
|
.up_tl ( up_tl ),
|
||||||
|
.up_dt1 ( up_dt1 ),
|
||||||
|
.up_ks_ar ( up_ks_ar ),
|
||||||
|
.up_amen_dr ( up_amen_dr ),
|
||||||
|
.up_sr ( up_sr ),
|
||||||
|
.up_sl_rr ( up_sl_rr ),
|
||||||
|
.up_ssgeg ( up_ssgeg ),
|
||||||
|
.update_op_I ( update_op_I ),
|
||||||
|
.update_op_II ( update_op_II ),
|
||||||
|
.update_op_IV ( update_op_IV )
|
||||||
);
|
);
|
||||||
|
|
||||||
assign regop_in = {
|
wire up_midop_I = { ~cur[4], cur[3:0] } == req_opch_I;
|
||||||
up_tl_op ? tl_in : tl_VII, // 7
|
wire up_midop_II = { ~cur[4], cur[3:0] } == req_opch_II;
|
||||||
up_dt1_op ? dt1_in : dt1_II, // 3
|
wire up_midop_IV = { ~cur[4], cur[3:0] } == req_opch_IV;
|
||||||
up_mul_op ? mul_in : mul_V, // 4 - 7
|
|
||||||
up_ks_op ? ks_in : ks_III, // 2 - 16
|
|
||||||
up_ar_op ? ar_in : ar_II, // 5 - 21
|
|
||||||
up_amen_op ? amen_in: amsen_VII,// 1 - 22
|
|
||||||
up_d1r_op ? d1r_in : d1r_II, // 5 - 25
|
|
||||||
up_d2r_op ? d2r_in : d2r_II, // 5 - 30
|
|
||||||
up_d1l_op ? d1l_in : d1l, // 4 - 34
|
|
||||||
up_rr_op ? rr_in : rr_II, // 4 - 38
|
|
||||||
up_ssg_op ? ssg_in[3] : ssg_en_II, // 1 - 39
|
|
||||||
up_ssg_op ? ssg_in[2:0] : ssg_eg_II // 3 - 42
|
|
||||||
};
|
|
||||||
|
|
||||||
assign { tl_VII, dt1_II, mul_V, ks_III,
|
jt12_csr u_csr1(
|
||||||
ar_II, amsen_VII, d1r_II, d2r_II, d1l, rr_II,
|
.rst ( rst ),
|
||||||
ssg_en_II, ssg_eg_II } = regop_out;
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.din ( din ),
|
||||||
|
.shift_in ( shift_middle ),
|
||||||
|
.shift_out ( shift_out ),
|
||||||
|
.up_tl ( up_tl ),
|
||||||
|
.up_dt1 ( up_dt1 ),
|
||||||
|
.up_ks_ar ( up_ks_ar ),
|
||||||
|
.up_amen_dr ( up_amen_dr ),
|
||||||
|
.up_sr ( up_sr ),
|
||||||
|
.up_sl_rr ( up_sl_rr ),
|
||||||
|
.up_ssgeg ( up_ssgeg ),
|
||||||
|
// update in the middle:
|
||||||
|
.update_op_I ( up_midop_I ),
|
||||||
|
.update_op_II ( up_midop_II ),
|
||||||
|
.update_op_IV ( up_midop_IV )
|
||||||
|
);
|
||||||
|
end
|
||||||
|
else begin // YM2203 only has one CSR
|
||||||
|
jt12_csr u_csr0(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.din ( din ),
|
||||||
|
.shift_in ( shift_out ),
|
||||||
|
.shift_out ( shift_out ),
|
||||||
|
.up_tl ( up_tl ),
|
||||||
|
.up_dt1 ( up_dt1 ),
|
||||||
|
.up_ks_ar ( up_ks_ar ),
|
||||||
|
.up_amen_dr ( up_amen_dr ),
|
||||||
|
.up_sr ( up_sr ),
|
||||||
|
.up_sl_rr ( up_sl_rr ),
|
||||||
|
.up_ssgeg ( up_ssgeg ),
|
||||||
|
.update_op_I ( update_op_I ),
|
||||||
|
.update_op_II ( update_op_II ),
|
||||||
|
.update_op_IV ( update_op_IV )
|
||||||
|
);
|
||||||
|
end // else
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign { tl_IV, dt1_I, mul_II, ks_II,
|
||||||
|
ar_I, amsen_IV, d1r_I, d2r_I,
|
||||||
|
sl_I, rr_I, ssg_en_I, ssg_eg_I } = shift_out;
|
||||||
|
|
||||||
wire [2:0] block_latch, fnum_latch;
|
|
||||||
|
|
||||||
// memory for CH registers
|
// memory for CH registers
|
||||||
// Block/fnum data is latched until fnum low byte is written to
|
// Block/fnum data is latched until fnum low byte is written to
|
||||||
// Trying to synthesize this memory as M-9K RAM in Altera devices
|
// Trying to synthesize this memory as M-9K RAM in Altera devices
|
||||||
// turns out worse in terms of resource utilization. Probably because
|
// turns out worse in terms of resource utilization. Probably because
|
||||||
// this memory is already very small. It is better to leave it as it is.
|
// this memory is already very small. It is better to leave it as it is.
|
||||||
parameter regch_width=31;
|
localparam regch_width=25;
|
||||||
wire [regch_width-1:0] regch_out;
|
wire [regch_width-1:0] regch_out;
|
||||||
wire [regch_width-1:0] regch_in = {
|
wire [regch_width-1:0] regch_in = {
|
||||||
up_block_ch ? { block_in, fnhi_in } : { block_latch, fnum_latch }, // 3+3
|
up_fnumlo_ch? { latch_fnum, fnlo_in } : { block_I_raw, fnum_I_raw }, // 14
|
||||||
up_fnumlo_ch? { block_latch, fnum_latch, fnlo_in } : { block_I_raw, fnum_I_raw }, // 14
|
up_alg_ch ? { fb_in, alg_in } : { fb_I, alg_I },//3+3
|
||||||
up_alg_ch ? { fb_in, alg_in } : { fb_I, alg },//3+3
|
up_ams_ch ? ams_in : ams_IV, //2
|
||||||
up_pms_ch ? { ams_in, pms_in } : { ams_VII, pms }//2+2+3
|
up_pms_ch ? pms_in : pms_I //3
|
||||||
};
|
};
|
||||||
|
|
||||||
assign { block_latch, fnum_latch,
|
assign { block_I_raw, fnum_I_raw,
|
||||||
block_I_raw, fnum_I_raw,
|
fb_I, alg_I, ams_IV, pms_I } = regch_out;
|
||||||
fb_I, alg, ams_VII, pms } = regch_out;
|
|
||||||
|
|
||||||
jt12_sh #(.width(regch_width),.stages(6)) u_regch(
|
jt12_sh_rst #(.width(regch_width),.stages(num_ch)) u_regch(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
//.rst ( rst ),
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
.din ( regch_in ),
|
.din ( regch_in ),
|
||||||
.drop ( regch_out )
|
.drop ( regch_out )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
generate
|
||||||
|
if( num_ch==6 ) begin
|
||||||
// RL is on a different register to
|
// RL is on a different register to
|
||||||
// have the reset to 1
|
// have the reset to 1
|
||||||
jt12_sh_rst #(.width(2),.stages(6),.rstval(1'b1)) u_regch_rl(
|
wire [1:0] rl_in = din[7:6];
|
||||||
|
jt12_sh_rst #(.width(2),.stages(num_ch),.rstval(1'b1)) u_regch_rl(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
// .rst ( rst ),
|
.clk_en ( clk_en ),
|
||||||
|
.rst ( rst ),
|
||||||
.din ( up_pms_ch ? rl_in : rl ),
|
.din ( up_pms_ch ? rl_in : rl ),
|
||||||
.drop ( rl )
|
.drop ( rl )
|
||||||
);
|
);
|
||||||
|
end else begin // YM2203 has no stereo output
|
||||||
|
assign rl=2'b11;
|
||||||
|
end
|
||||||
|
|
||||||
|
endgenerate
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -20,9 +20,11 @@
|
|||||||
|
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
// stages must be greater than 2
|
||||||
module jt12_sh #(parameter width=5, stages=24 )
|
module jt12_sh #(parameter width=5, stages=24 )
|
||||||
(
|
(
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input [width-1:0] din,
|
input [width-1:0] din,
|
||||||
output [width-1:0] drop
|
output [width-1:0] drop
|
||||||
);
|
);
|
||||||
@ -32,11 +34,8 @@ reg [stages-1:0] bits[width-1:0];
|
|||||||
genvar i;
|
genvar i;
|
||||||
generate
|
generate
|
||||||
for (i=0; i < width; i=i+1) begin: bit_shifter
|
for (i=0; i < width; i=i+1) begin: bit_shifter
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if(clk_en) begin
|
||||||
if( stages> 1 )
|
|
||||||
bits[i] <= {bits[i][stages-2:0], din[i]};
|
bits[i] <= {bits[i][stages-2:0], din[i]};
|
||||||
else
|
|
||||||
bits[i] <= din[i];
|
|
||||||
end
|
end
|
||||||
assign drop[i] = bits[i][stages-1];
|
assign drop[i] = bits[i][stages-1];
|
||||||
end
|
end
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
module jt12_sh24 #(parameter width=5 )
|
module jt12_sh24 #(parameter width=5 )
|
||||||
(
|
(
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input [width-1:0] din,
|
input [width-1:0] din,
|
||||||
output reg [width-1:0] st1,
|
output reg [width-1:0] st1,
|
||||||
output reg [width-1:0] st2,
|
output reg [width-1:0] st2,
|
||||||
@ -50,7 +51,7 @@ module jt12_sh24 #(parameter width=5 )
|
|||||||
output reg [width-1:0] st24
|
output reg [width-1:0] st24
|
||||||
);
|
);
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) if(clk_en) begin
|
||||||
st24<= st23;
|
st24<= st23;
|
||||||
st23<= st22;
|
st23<= st22;
|
||||||
st22<= st21;
|
st22<= st21;
|
||||||
|
@ -20,10 +20,12 @@
|
|||||||
|
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
// stages must be greater than 2
|
||||||
module jt12_sh_rst #(parameter width=5, stages=32, rstval=1'b0 )
|
module jt12_sh_rst #(parameter width=5, stages=32, rstval=1'b0 )
|
||||||
(
|
(
|
||||||
// input rst,
|
input rst,
|
||||||
input clk,
|
input clk,
|
||||||
|
input clk_en,
|
||||||
input [width-1:0] din,
|
input [width-1:0] din,
|
||||||
output [width-1:0] drop
|
output [width-1:0] drop
|
||||||
);
|
);
|
||||||
@ -35,17 +37,17 @@ integer k;
|
|||||||
generate
|
generate
|
||||||
initial
|
initial
|
||||||
for (k=0; k < width; k=k+1) begin
|
for (k=0; k < width; k=k+1) begin
|
||||||
bits[k] <= { stages{rstval}};
|
bits[k] = { stages{rstval}};
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
generate
|
generate
|
||||||
for (i=0; i < width; i=i+1) begin: bit_shifter
|
for (i=0; i < width; i=i+1) begin: bit_shifter
|
||||||
always @(posedge clk) begin
|
always @(posedge clk)
|
||||||
if( stages> 1 )
|
if( rst ) begin
|
||||||
|
bits[i] <= {stages{rstval}};
|
||||||
|
end else if(clk_en) begin
|
||||||
bits[i] <= {bits[i][stages-2:0], din[i]};
|
bits[i] <= {bits[i][stages-2:0], din[i]};
|
||||||
else
|
|
||||||
bits[i] <= din[i];
|
|
||||||
end
|
end
|
||||||
assign drop[i] = bits[i][stages-1];
|
assign drop[i] = bits[i][stages-1];
|
||||||
end
|
end
|
||||||
|
59
rtl/sound/jt12/jt12_single_acc.v
Normal file
59
rtl/sound/jt12/jt12_single_acc.v
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 27-1-2017
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
module jt12_single_acc #(parameter win=14, // input data width
|
||||||
|
wout=16 // output data width
|
||||||
|
)(
|
||||||
|
input clk,
|
||||||
|
input clk_en,
|
||||||
|
input [win-1:0] op_result,
|
||||||
|
input sum_en,
|
||||||
|
input zero,
|
||||||
|
output reg [wout-1:0] snd
|
||||||
|
);
|
||||||
|
|
||||||
|
// for full resolution use win=14, wout=16
|
||||||
|
// for cut down resolution use win=9, wout=12
|
||||||
|
// wout-win should be > 0
|
||||||
|
|
||||||
|
reg signed [wout-1:0] next, acc, current;
|
||||||
|
reg overflow;
|
||||||
|
|
||||||
|
wire [wout-1:0] plus_inf = { 1'b0, {(wout-1){1'b1}} }; // maximum positive value
|
||||||
|
wire [wout-1:0] minus_inf = { 1'b1, {(wout-1){1'b0}} }; // minimum negative value
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
current = sum_en ? { {(wout-win){op_result[win-1]}}, op_result } : {wout{1'b0}};
|
||||||
|
next = zero ? current : current + acc;
|
||||||
|
overflow = !zero &&
|
||||||
|
(current[wout-1] == acc[wout-1]) &&
|
||||||
|
(acc[wout-1]!=next[wout-1]);
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) if( clk_en ) begin
|
||||||
|
acc <= overflow ? (acc[wout-1] ? minus_inf : plus_inf) : next;
|
||||||
|
if(zero) snd <= acc;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // jt12_single_acc
|
@ -20,18 +20,28 @@
|
|||||||
|
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
/* The input is {op[1:0], ch[2:0]}
|
||||||
|
it adds 1 to the channel and overflow to the operator correctly */
|
||||||
|
|
||||||
module jt12_sumch
|
module jt12_sumch
|
||||||
(
|
(
|
||||||
input [4:0] chin,
|
input [4:0] chin,
|
||||||
output reg [4:0] chout
|
output reg [4:0] chout
|
||||||
);
|
);
|
||||||
|
|
||||||
|
parameter num_ch=6;
|
||||||
|
|
||||||
reg [2:0] aux;
|
reg [2:0] aux;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
aux <= chin[2:0] + 3'd1;
|
aux = chin[2:0] + 3'd1;
|
||||||
chout[2:0] <= aux[1:0]==2'b11 ? aux+3'd1 : aux;
|
if( num_ch==6 ) begin
|
||||||
chout[4:3] <= chin[2:0]==3'd6 ? chin[4:3]+2'd1 : chin[4:3];
|
chout[2:0] = aux[1:0]==2'b11 ? aux+3'd1 : aux;
|
||||||
|
chout[4:3] = chin[2:0]==3'd6 ? chin[4:3]+2'd1 : chin[4:3]; // next operator
|
||||||
|
end else begin // 3 channels
|
||||||
|
chout[2:0] = aux[1:0]==2'b11 ? 3'd0 : aux;
|
||||||
|
chout[4:3] = chin[2:0]==3'd2 ? chin[4:3]+2'd1 : chin[4:3]; // next operator
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,338 +0,0 @@
|
|||||||
module jt12_syn(
|
|
||||||
input rst,
|
|
||||||
input clk, // cpu_clk/6 ~ 1.3MHz
|
|
||||||
input [7:0] din,
|
|
||||||
input [1:0] addr,
|
|
||||||
input write,
|
|
||||||
input limiter_en,
|
|
||||||
|
|
||||||
output busy,
|
|
||||||
output flag_A,
|
|
||||||
output flag_B,
|
|
||||||
output irq_n,
|
|
||||||
// combined output
|
|
||||||
output signed [11:0] snd_right,
|
|
||||||
output signed [11:0] snd_left,
|
|
||||||
output snd_sample,
|
|
||||||
// multiplexed output
|
|
||||||
output signed [8:0] mux_right,
|
|
||||||
output signed [8:0] mux_left,
|
|
||||||
output mux_sample
|
|
||||||
);
|
|
||||||
// Timers
|
|
||||||
wire [9:0] value_A;
|
|
||||||
wire [7:0] value_B;
|
|
||||||
wire load_A, load_B;
|
|
||||||
wire enable_irq_A, enable_irq_B;
|
|
||||||
wire clr_flag_A, clr_flag_B;
|
|
||||||
wire overflow_A;
|
|
||||||
wire fast_timers;
|
|
||||||
|
|
||||||
wire zero; // Single-clock pulse at the begginig of s1_enters
|
|
||||||
// LFO
|
|
||||||
wire [2:0] lfo_freq;
|
|
||||||
wire lfo_en;
|
|
||||||
// Operators
|
|
||||||
wire amsen_VII;
|
|
||||||
wire [ 2:0] dt1_II;
|
|
||||||
wire [ 3:0] mul_V;
|
|
||||||
wire [ 6:0] tl_VII;
|
|
||||||
|
|
||||||
wire [4:0] keycode_III;
|
|
||||||
wire [ 4:0] ar_II;
|
|
||||||
wire [ 4:0] d1r_II;
|
|
||||||
wire [ 4:0] d2r_II;
|
|
||||||
wire [ 3:0] rr_II;
|
|
||||||
wire [ 3:0] d1l;
|
|
||||||
wire [ 1:0] ks_III;
|
|
||||||
// SSG operation
|
|
||||||
wire ssg_en_II;
|
|
||||||
wire [2:0] ssg_eg_II;
|
|
||||||
// envelope operation
|
|
||||||
wire keyon_II;
|
|
||||||
wire [9:0] eg_IX;
|
|
||||||
wire pg_rst_III;
|
|
||||||
// Channel
|
|
||||||
wire [10:0] fnum_I;
|
|
||||||
wire [ 2:0] block_I;
|
|
||||||
wire [ 1:0] rl;
|
|
||||||
wire [ 2:0] fb_II;
|
|
||||||
wire [ 2:0] alg;
|
|
||||||
wire [ 2:0] pms;
|
|
||||||
wire [ 1:0] ams_VII;
|
|
||||||
// PCM
|
|
||||||
wire pcm_en;
|
|
||||||
wire [ 8:0] pcm;
|
|
||||||
// Test
|
|
||||||
wire pg_stop, eg_stop;
|
|
||||||
|
|
||||||
wire ch6op;
|
|
||||||
|
|
||||||
// Operator
|
|
||||||
wire use_internal_x, use_internal_y;
|
|
||||||
wire use_prevprev1, use_prev2, use_prev1;
|
|
||||||
wire [ 9:0] phase_VIII;
|
|
||||||
wire s1_enters, s2_enters, s3_enters, s4_enters;
|
|
||||||
wire rst_int;
|
|
||||||
// LFO
|
|
||||||
wire [6:0] lfo_mod;
|
|
||||||
wire lfo_rst;
|
|
||||||
|
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
// Test bits
|
|
||||||
wire test_eg, test_op0;
|
|
||||||
`endif
|
|
||||||
|
|
||||||
jt12_mmr u_mmr(
|
|
||||||
.rst ( rst ),
|
|
||||||
.clk ( clk ),
|
|
||||||
.din ( din ),
|
|
||||||
.write ( write ),
|
|
||||||
.addr ( addr ),
|
|
||||||
.busy ( busy ),
|
|
||||||
.ch6op ( ch6op ),
|
|
||||||
// LFO
|
|
||||||
.lfo_freq ( lfo_freq ),
|
|
||||||
.lfo_en ( lfo_en ),
|
|
||||||
// Timers
|
|
||||||
.value_A ( value_A ),
|
|
||||||
.value_B ( value_B ),
|
|
||||||
.load_A ( load_A ),
|
|
||||||
.load_B ( load_B ),
|
|
||||||
.enable_irq_A ( enable_irq_A ),
|
|
||||||
.enable_irq_B ( enable_irq_B ),
|
|
||||||
.clr_flag_A ( clr_flag_A ),
|
|
||||||
.clr_flag_B ( clr_flag_B ),
|
|
||||||
.flag_A ( flag_A ),
|
|
||||||
.overflow_A ( overflow_A ),
|
|
||||||
.fast_timers( fast_timers ),
|
|
||||||
// PCM
|
|
||||||
.pcm ( pcm ),
|
|
||||||
.pcm_en ( pcm_en ),
|
|
||||||
|
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
// Test
|
|
||||||
.test_eg ( test_eg ),
|
|
||||||
.test_op0 ( test_op0 ),
|
|
||||||
`endif
|
|
||||||
// Operator
|
|
||||||
.use_prevprev1 ( use_prevprev1 ),
|
|
||||||
.use_internal_x ( use_internal_x ),
|
|
||||||
.use_internal_y ( use_internal_y ),
|
|
||||||
.use_prev2 ( use_prev2 ),
|
|
||||||
.use_prev1 ( use_prev1 ),
|
|
||||||
// PG
|
|
||||||
.fnum_I ( fnum_I ),
|
|
||||||
.block_I ( block_I ),
|
|
||||||
.pg_stop ( pg_stop ),
|
|
||||||
// EG
|
|
||||||
.rl ( rl ),
|
|
||||||
.fb_II ( fb_II ),
|
|
||||||
.alg ( alg ),
|
|
||||||
.pms ( pms ),
|
|
||||||
.ams_VII ( ams_VII ),
|
|
||||||
.amsen_VII ( amsen_VII ),
|
|
||||||
.dt1_II ( dt1_II ),
|
|
||||||
.mul_V ( mul_V ),
|
|
||||||
.tl_VII ( tl_VII ),
|
|
||||||
|
|
||||||
.ar_II ( ar_II ),
|
|
||||||
.d1r_II ( d1r_II ),
|
|
||||||
.d2r_II ( d2r_II ),
|
|
||||||
.rr_II ( rr_II ),
|
|
||||||
.d1l ( d1l ),
|
|
||||||
.ks_III ( ks_III ),
|
|
||||||
|
|
||||||
.eg_stop ( eg_stop ),
|
|
||||||
// SSG operation
|
|
||||||
.ssg_en_II ( ssg_en_II ),
|
|
||||||
.ssg_eg_II ( ssg_eg_II ),
|
|
||||||
|
|
||||||
.keyon_II ( keyon_II ),
|
|
||||||
// Operator
|
|
||||||
.zero ( zero ),
|
|
||||||
.s1_enters ( s1_enters ),
|
|
||||||
.s2_enters ( s2_enters ),
|
|
||||||
.s3_enters ( s3_enters ),
|
|
||||||
.s4_enters ( s4_enters )
|
|
||||||
);
|
|
||||||
|
|
||||||
jt12_timers u_timers(
|
|
||||||
.clk ( clk ),
|
|
||||||
.rst ( rst ),
|
|
||||||
.clk_en ( zero ),
|
|
||||||
.fast_timers( fast_timers ), // fix this to work well with clock enable signals
|
|
||||||
.value_A ( value_A ),
|
|
||||||
.value_B ( value_B ),
|
|
||||||
.load_A ( load_A ),
|
|
||||||
.load_B ( load_B ),
|
|
||||||
.enable_irq_A( enable_irq_B ),
|
|
||||||
.enable_irq_B( enable_irq_A ),
|
|
||||||
.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 )
|
|
||||||
);
|
|
||||||
|
|
||||||
jt12_lfo u_lfo(
|
|
||||||
.rst ( rst ),
|
|
||||||
.clk ( clk ),
|
|
||||||
.zero ( zero ),
|
|
||||||
.lfo_rst ( 1'b0 ),
|
|
||||||
.lfo_en ( lfo_en ),
|
|
||||||
.lfo_freq ( lfo_freq ),
|
|
||||||
.lfo_mod ( lfo_mod )
|
|
||||||
);
|
|
||||||
|
|
||||||
`ifndef TIMERONLY
|
|
||||||
|
|
||||||
jt12_pg u_pg(
|
|
||||||
.clk ( clk ),
|
|
||||||
.rst ( rst ),
|
|
||||||
// Channel frequency
|
|
||||||
.fnum_I ( fnum_I ),
|
|
||||||
.block_I ( block_I ),
|
|
||||||
// Operator multiplying
|
|
||||||
.mul_V ( mul_V ),
|
|
||||||
// Operator detuning
|
|
||||||
.dt1_II ( dt1_II ), // same as JT51's DT1
|
|
||||||
// phase operation
|
|
||||||
.pg_rst_III ( pg_rst_III ),
|
|
||||||
.zero ( zero ),
|
|
||||||
.pg_stop ( pg_stop ),
|
|
||||||
.keycode_III( keycode_III ),
|
|
||||||
.phase_VIII ( phase_VIII )
|
|
||||||
);
|
|
||||||
|
|
||||||
jt12_eg u_eg(
|
|
||||||
`ifdef TEST_SUPPORT
|
|
||||||
.test_eg ( test_eg ),
|
|
||||||
`endif
|
|
||||||
.rst ( rst ),
|
|
||||||
.clk ( clk ),
|
|
||||||
.zero ( zero ),
|
|
||||||
.eg_stop ( eg_stop ),
|
|
||||||
// envelope configuration
|
|
||||||
.keycode_III ( keycode_III ),
|
|
||||||
.arate_II ( ar_II ), // attack rate
|
|
||||||
.rate1_II ( d1r_II ), // decay rate
|
|
||||||
.rate2_II ( d2r_II ), // sustain rate
|
|
||||||
.rrate_II ( rr_II ), // release rate
|
|
||||||
.d1l ( d1l ), // sustain level
|
|
||||||
.ks_III ( ks_III ), // key scale
|
|
||||||
// SSG operation
|
|
||||||
.ssg_en_II ( ssg_en_II ),
|
|
||||||
.ssg_eg_II ( ssg_eg_II ),
|
|
||||||
// envelope operation
|
|
||||||
.keyon_II ( keyon_II ),
|
|
||||||
// envelope number
|
|
||||||
.am ( lfo_mod ),
|
|
||||||
.tl_VII ( tl_VII ),
|
|
||||||
.ams_VII ( ams_VII ),
|
|
||||||
.amsen_VII ( amsen_VII ),
|
|
||||||
|
|
||||||
.eg_IX ( eg_IX ),
|
|
||||||
.pg_rst_III ( pg_rst_III )
|
|
||||||
);
|
|
||||||
|
|
||||||
wire [8:0] op_result;
|
|
||||||
|
|
||||||
jt12_op u_op(
|
|
||||||
.rst ( rst ),
|
|
||||||
.clk ( clk ),
|
|
||||||
.pg_phase_VIII ( phase_VIII ),
|
|
||||||
.eg_atten_IX ( eg_IX ),
|
|
||||||
.fb_II ( fb_II ),
|
|
||||||
|
|
||||||
.test_214 ( 1'b0 ),
|
|
||||||
.s1_enters ( s1_enters ),
|
|
||||||
.s2_enters ( s2_enters ),
|
|
||||||
.s3_enters ( s3_enters ),
|
|
||||||
.s4_enters ( s4_enters ),
|
|
||||||
.use_prevprev1 ( use_prevprev1 ),
|
|
||||||
.use_internal_x ( use_internal_x),
|
|
||||||
.use_internal_y ( use_internal_y),
|
|
||||||
.use_prev2 ( use_prev2 ),
|
|
||||||
.use_prev1 ( use_prev1 ),
|
|
||||||
.zero ( zero ),
|
|
||||||
.op_result ( op_result )
|
|
||||||
);
|
|
||||||
|
|
||||||
jt12_acc u_acc(
|
|
||||||
.rst ( rst ),
|
|
||||||
.clk ( clk ),
|
|
||||||
.op_result ( op_result ),
|
|
||||||
.rl ( rl ),
|
|
||||||
.limiter_en ( limiter_en),
|
|
||||||
// note that the order changes to deal
|
|
||||||
// with the operator pipeline delay
|
|
||||||
.s1_enters ( s2_enters ),
|
|
||||||
.s2_enters ( s1_enters ),
|
|
||||||
.s3_enters ( s4_enters ),
|
|
||||||
.s4_enters ( s3_enters ),
|
|
||||||
.ch6op ( ch6op ),
|
|
||||||
.pcm_en ( pcm_en ), // only enabled for channel 6
|
|
||||||
.pcm ( pcm ),
|
|
||||||
.alg ( alg ),
|
|
||||||
// combined output
|
|
||||||
.left ( snd_left ),
|
|
||||||
.right ( snd_right ),
|
|
||||||
.sample ( snd_sample),
|
|
||||||
// muxed output
|
|
||||||
.mux_left ( mux_left ),
|
|
||||||
.mux_right ( mux_right ),
|
|
||||||
.mux_sample ( mux_sample)
|
|
||||||
);
|
|
||||||
|
|
||||||
`ifdef SIMULATION
|
|
||||||
reg [4:0] sep24_cnt;
|
|
||||||
|
|
||||||
wire [9:0] eg_ch0s1, eg_ch1s1, eg_ch2s1, eg_ch3s1, eg_ch4s1, eg_ch5s1,
|
|
||||||
eg_ch0s2, eg_ch1s2, eg_ch2s2, eg_ch3s2, eg_ch4s2, eg_ch5s2,
|
|
||||||
eg_ch0s3, eg_ch1s3, eg_ch2s3, eg_ch3s3, eg_ch4s3, eg_ch5s3,
|
|
||||||
eg_ch0s4, eg_ch1s4, eg_ch2s4, eg_ch3s4, eg_ch4s4, eg_ch5s4;
|
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
|
||||||
|
|
||||||
sep24 #( .width(10), .pos0(5'd0)) egsep
|
|
||||||
(
|
|
||||||
.clk ( clk ),
|
|
||||||
.mixed ( eg_IX ),
|
|
||||||
.mask ( 10'd0 ),
|
|
||||||
.cnt ( sep24_cnt ),
|
|
||||||
|
|
||||||
.ch0s1 (eg_ch0s1),
|
|
||||||
.ch1s1 (eg_ch1s1),
|
|
||||||
.ch2s1 (eg_ch2s1),
|
|
||||||
.ch3s1 (eg_ch3s1),
|
|
||||||
.ch4s1 (eg_ch4s1),
|
|
||||||
.ch5s1 (eg_ch5s1),
|
|
||||||
|
|
||||||
.ch0s2 (eg_ch0s2),
|
|
||||||
.ch1s2 (eg_ch1s2),
|
|
||||||
.ch2s2 (eg_ch2s2),
|
|
||||||
.ch3s2 (eg_ch3s2),
|
|
||||||
.ch4s2 (eg_ch4s2),
|
|
||||||
.ch5s2 (eg_ch5s2),
|
|
||||||
|
|
||||||
.ch0s3 (eg_ch0s3),
|
|
||||||
.ch1s3 (eg_ch1s3),
|
|
||||||
.ch2s3 (eg_ch2s3),
|
|
||||||
.ch3s3 (eg_ch3s3),
|
|
||||||
.ch4s3 (eg_ch4s3),
|
|
||||||
.ch5s3 (eg_ch5s3),
|
|
||||||
|
|
||||||
.ch0s4 (eg_ch0s4),
|
|
||||||
.ch1s4 (eg_ch1s4),
|
|
||||||
.ch2s4 (eg_ch2s4),
|
|
||||||
.ch3s4 (eg_ch3s4),
|
|
||||||
.ch4s4 (eg_ch4s4),
|
|
||||||
.ch5s4 (eg_ch5s4)
|
|
||||||
);
|
|
||||||
`endif
|
|
||||||
|
|
||||||
`endif
|
|
||||||
endmodule
|
|
@ -28,7 +28,6 @@ module jt12_timers(
|
|||||||
input clk,
|
input clk,
|
||||||
input rst,
|
input rst,
|
||||||
input clk_en, // clock enable
|
input clk_en, // clock enable
|
||||||
input fast_timers,
|
|
||||||
input [9:0] value_A,
|
input [9:0] value_A,
|
||||||
input [7:0] value_B,
|
input [7:0] value_B,
|
||||||
input load_A,
|
input load_A,
|
||||||
@ -45,11 +44,11 @@ module jt12_timers(
|
|||||||
|
|
||||||
assign irq_n = ~( (flag_A&enable_irq_A) | (flag_B&enable_irq_B) );
|
assign irq_n = ~( (flag_A&enable_irq_A) | (flag_B&enable_irq_B) );
|
||||||
|
|
||||||
jt12_timer #(.mult_width(1), .mult_max(0), .counter_width(10))
|
jt12_timer #(.mult_width(5), .mult_max(24), .counter_width(10))
|
||||||
timer_A(
|
timer_A(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.rst ( rst ),
|
.rst ( rst ),
|
||||||
.clk_en ( clk_en | fast_timers ),
|
.clk_en ( clk_en ),
|
||||||
.start_value( value_A ),
|
.start_value( value_A ),
|
||||||
.load ( load_A ),
|
.load ( load_A ),
|
||||||
.clr_flag ( clr_flag_A),
|
.clr_flag ( clr_flag_A),
|
||||||
@ -57,11 +56,11 @@ timer_A(
|
|||||||
.overflow ( overflow_A)
|
.overflow ( overflow_A)
|
||||||
);
|
);
|
||||||
|
|
||||||
jt12_timer #(.mult_width(4), .mult_max(15), .counter_width(8))
|
jt12_timer #(.mult_width(9), .mult_max(384), .counter_width(8))
|
||||||
timer_B(
|
timer_B(
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.rst ( rst ),
|
.rst ( rst ),
|
||||||
.clk_en ( clk_en | fast_timers ),
|
.clk_en ( clk_en ),
|
||||||
.start_value( value_B ),
|
.start_value( value_B ),
|
||||||
.load ( load_B ),
|
.load ( load_B ),
|
||||||
.clr_flag ( clr_flag_B),
|
.clr_flag ( clr_flag_B),
|
||||||
@ -94,15 +93,17 @@ always@(posedge clk)
|
|||||||
reg [mult_width+counter_width-1:0] next, init;
|
reg [mult_width+counter_width-1:0] next, init;
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
if( mult<mult_max )
|
if( mult<mult_max ) begin
|
||||||
{overflow, next } <= { {1'b0, cnt}, mult+1'b1 } ;
|
// mult not meant to overflow in this line
|
||||||
else
|
{overflow, next } = { {1'b0, cnt}, mult+1'b1 } ;
|
||||||
{overflow, next } <= { {1'b0, cnt}+1'b1, {mult_width{1'b0}} };
|
end else begin
|
||||||
init <= { start_value, {mult_width{1'b0}} };
|
{overflow, next } = { {1'b0, cnt}+1'b1, {mult_width{1'b0}} };
|
||||||
|
end
|
||||||
|
init = { start_value, {mult_width{1'b0}} };
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( load || rst) begin
|
if( ~load || rst) begin
|
||||||
mult <= { (mult_width){1'b0} };
|
mult <= { (mult_width){1'b0} };
|
||||||
cnt <= start_value;
|
cnt <= start_value;
|
||||||
end
|
end
|
||||||
|
476
rtl/sound/jt12/jt12_top.v
Normal file
476
rtl/sound/jt12/jt12_top.v
Normal file
@ -0,0 +1,476 @@
|
|||||||
|
/* This file is part of JT12.
|
||||||
|
|
||||||
|
JT12 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.
|
||||||
|
|
||||||
|
JT12 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 JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||||
|
Version: 1.0
|
||||||
|
Date: 14-2-2016
|
||||||
|
|
||||||
|
Based on information posted by Nemesis on:
|
||||||
|
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||||
|
|
||||||
|
Based on jt51_phasegen.v, from JT51
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module jt12_top (
|
||||||
|
input rst, // rst should be at least 6 clk&cen cycles long
|
||||||
|
input clk, // CPU clock
|
||||||
|
input cen, // optional clock enable, it not needed leave as 1'b1
|
||||||
|
input [7:0] din,
|
||||||
|
input [1:0] addr,
|
||||||
|
input cs_n,
|
||||||
|
input wr_n,
|
||||||
|
|
||||||
|
output [7:0] dout,
|
||||||
|
output irq_n,
|
||||||
|
// Separated output
|
||||||
|
output [ 7:0] psg_A,
|
||||||
|
output [ 7:0] psg_B,
|
||||||
|
output [ 7:0] psg_C,
|
||||||
|
output signed [15:0] fm_snd_left,
|
||||||
|
output signed [15:0] fm_snd_right,
|
||||||
|
// combined output
|
||||||
|
output [ 9:0] psg_snd,
|
||||||
|
output signed [15:0] snd_right, // FM+PSG
|
||||||
|
output signed [15:0] snd_left, // FM+PSG
|
||||||
|
output snd_sample
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter use_lfo=1, use_ssg=0, num_ch=6, use_pcm=1, use_lr=1; // defaults to YM2612
|
||||||
|
|
||||||
|
wire flag_A, flag_B, busy;
|
||||||
|
|
||||||
|
wire [7:0] fm_dout = { busy, 5'd0, flag_B, flag_A };
|
||||||
|
wire write = !cs_n && !wr_n;
|
||||||
|
wire clk_en, clk_en_ssg;
|
||||||
|
|
||||||
|
// Timers
|
||||||
|
wire [9:0] value_A;
|
||||||
|
wire [7:0] value_B;
|
||||||
|
wire load_A, load_B;
|
||||||
|
wire enable_irq_A, enable_irq_B;
|
||||||
|
wire clr_flag_A, clr_flag_B;
|
||||||
|
wire overflow_A;
|
||||||
|
wire fast_timers;
|
||||||
|
|
||||||
|
wire zero; // Single-clock pulse at the begginig of s1_enters
|
||||||
|
// LFO
|
||||||
|
wire [2:0] lfo_freq;
|
||||||
|
wire lfo_en;
|
||||||
|
// Operators
|
||||||
|
wire amsen_IV;
|
||||||
|
wire [ 2:0] dt1_I;
|
||||||
|
wire [ 3:0] mul_II;
|
||||||
|
wire [ 6:0] tl_IV;
|
||||||
|
|
||||||
|
wire [ 4:0] keycode_II;
|
||||||
|
wire [ 4:0] ar_I;
|
||||||
|
wire [ 4:0] d1r_I;
|
||||||
|
wire [ 4:0] d2r_I;
|
||||||
|
wire [ 3:0] rr_I;
|
||||||
|
wire [ 3:0] sl_I;
|
||||||
|
wire [ 1:0] ks_II;
|
||||||
|
// SSG operation
|
||||||
|
wire ssg_en_I;
|
||||||
|
wire [2:0] ssg_eg_I;
|
||||||
|
// envelope operation
|
||||||
|
wire keyon_I;
|
||||||
|
wire [9:0] eg_IX;
|
||||||
|
wire pg_rst_II;
|
||||||
|
// Channel
|
||||||
|
wire [10:0] fnum_I;
|
||||||
|
wire [ 2:0] block_I;
|
||||||
|
wire [ 1:0] rl;
|
||||||
|
wire [ 2:0] fb_II;
|
||||||
|
wire [ 2:0] alg_I;
|
||||||
|
wire [ 2:0] pms_I;
|
||||||
|
wire [ 1:0] ams_IV;
|
||||||
|
// PCM
|
||||||
|
wire pcm_en, pcm_wr;
|
||||||
|
wire [ 8:0] pcm;
|
||||||
|
// Test
|
||||||
|
wire pg_stop, eg_stop;
|
||||||
|
|
||||||
|
wire ch6op;
|
||||||
|
|
||||||
|
// Operator
|
||||||
|
wire xuse_internal, yuse_internal;
|
||||||
|
wire xuse_prevprev1, xuse_prev2, yuse_prev1, yuse_prev2;
|
||||||
|
wire [ 9:0] phase_VIII;
|
||||||
|
wire s1_enters, s2_enters, s3_enters, s4_enters;
|
||||||
|
wire rst_int;
|
||||||
|
// LFO
|
||||||
|
wire [6:0] lfo_mod;
|
||||||
|
wire lfo_rst;
|
||||||
|
// PSG
|
||||||
|
wire [3:0] psg_addr;
|
||||||
|
wire [7:0] psg_data, psg_dout;
|
||||||
|
wire psg_wr_n;
|
||||||
|
|
||||||
|
jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm))
|
||||||
|
u_mmr(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.cen ( cen ), // external clock enable
|
||||||
|
.clk_en ( clk_en ), // internal clock enable
|
||||||
|
.clk_en_ssg ( clk_en_ssg), // internal clock enable
|
||||||
|
.din ( din ),
|
||||||
|
.write ( write ),
|
||||||
|
.addr ( addr ),
|
||||||
|
.busy ( busy ),
|
||||||
|
.ch6op ( ch6op ),
|
||||||
|
// LFO
|
||||||
|
.lfo_freq ( lfo_freq ),
|
||||||
|
.lfo_en ( lfo_en ),
|
||||||
|
// Timers
|
||||||
|
.value_A ( value_A ),
|
||||||
|
.value_B ( value_B ),
|
||||||
|
.load_A ( load_A ),
|
||||||
|
.load_B ( load_B ),
|
||||||
|
.enable_irq_A ( enable_irq_A ),
|
||||||
|
.enable_irq_B ( enable_irq_B ),
|
||||||
|
.clr_flag_A ( clr_flag_A ),
|
||||||
|
.clr_flag_B ( clr_flag_B ),
|
||||||
|
.flag_A ( flag_A ),
|
||||||
|
.overflow_A ( overflow_A ),
|
||||||
|
.fast_timers( fast_timers ),
|
||||||
|
// PCM
|
||||||
|
.pcm ( pcm ),
|
||||||
|
.pcm_en ( pcm_en ),
|
||||||
|
.pcm_wr ( pcm_wr ),
|
||||||
|
|
||||||
|
// Operator
|
||||||
|
.xuse_prevprev1 ( xuse_prevprev1 ),
|
||||||
|
.xuse_internal ( xuse_internal ),
|
||||||
|
.yuse_internal ( yuse_internal ),
|
||||||
|
.xuse_prev2 ( xuse_prev2 ),
|
||||||
|
.yuse_prev1 ( yuse_prev1 ),
|
||||||
|
.yuse_prev2 ( yuse_prev2 ),
|
||||||
|
// PG
|
||||||
|
.fnum_I ( fnum_I ),
|
||||||
|
.block_I ( block_I ),
|
||||||
|
.pg_stop ( pg_stop ),
|
||||||
|
// EG
|
||||||
|
.rl ( rl ),
|
||||||
|
.fb_II ( fb_II ),
|
||||||
|
.alg_I ( alg_I ),
|
||||||
|
.pms_I ( pms_I ),
|
||||||
|
.ams_IV ( ams_IV ),
|
||||||
|
.amsen_IV ( amsen_IV ),
|
||||||
|
.dt1_I ( dt1_I ),
|
||||||
|
.mul_II ( mul_II ),
|
||||||
|
.tl_IV ( tl_IV ),
|
||||||
|
|
||||||
|
.ar_I ( ar_I ),
|
||||||
|
.d1r_I ( d1r_I ),
|
||||||
|
.d2r_I ( d2r_I ),
|
||||||
|
.rr_I ( rr_I ),
|
||||||
|
.sl_I ( sl_I ),
|
||||||
|
.ks_II ( ks_II ),
|
||||||
|
|
||||||
|
.eg_stop ( eg_stop ),
|
||||||
|
// SSG operation
|
||||||
|
.ssg_en_I ( ssg_en_I ),
|
||||||
|
.ssg_eg_I ( ssg_eg_I ),
|
||||||
|
|
||||||
|
.keyon_I ( keyon_I ),
|
||||||
|
// Operator
|
||||||
|
.zero ( zero ),
|
||||||
|
.s1_enters ( s1_enters ),
|
||||||
|
.s2_enters ( s2_enters ),
|
||||||
|
.s3_enters ( s3_enters ),
|
||||||
|
.s4_enters ( s4_enters ),
|
||||||
|
// PSG interace
|
||||||
|
.psg_addr ( psg_addr ),
|
||||||
|
.psg_data ( psg_data ),
|
||||||
|
.psg_wr_n ( psg_wr_n )
|
||||||
|
);
|
||||||
|
|
||||||
|
jt12_timers u_timers(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en | fast_timers ),
|
||||||
|
.rst ( rst ),
|
||||||
|
.value_A ( value_A ),
|
||||||
|
.value_B ( value_B ),
|
||||||
|
.load_A ( load_A ),
|
||||||
|
.load_B ( load_B ),
|
||||||
|
.enable_irq_A( enable_irq_B ),
|
||||||
|
.enable_irq_B( enable_irq_A ),
|
||||||
|
.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 )
|
||||||
|
);
|
||||||
|
|
||||||
|
// YM2203 does not have LFO
|
||||||
|
generate
|
||||||
|
if( use_lfo== 1)
|
||||||
|
jt12_lfo u_lfo(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.zero ( zero ),
|
||||||
|
`ifdef NOLFO
|
||||||
|
.lfo_rst ( 1'b1 ),
|
||||||
|
`else
|
||||||
|
.lfo_rst ( 1'b0 ),
|
||||||
|
`endif
|
||||||
|
.lfo_en ( lfo_en ),
|
||||||
|
.lfo_freq ( lfo_freq ),
|
||||||
|
.lfo_mod ( lfo_mod )
|
||||||
|
);
|
||||||
|
else
|
||||||
|
assign lfo_mod = 7'd0;
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
// YM2203/YM2610 have a PSG
|
||||||
|
|
||||||
|
generate
|
||||||
|
if( use_ssg==1 ) begin
|
||||||
|
ym2149 u_psg
|
||||||
|
(
|
||||||
|
.CLK(clk),
|
||||||
|
.CE(clk_en_ssg),
|
||||||
|
.RESET(rst),
|
||||||
|
|
||||||
|
.BDIR(write),
|
||||||
|
.BC(~addr[0] | ~write),
|
||||||
|
.DI(din),
|
||||||
|
.DO(psg_dout),
|
||||||
|
.CHANNEL_A(psg_A),
|
||||||
|
.CHANNEL_B(psg_B),
|
||||||
|
.CHANNEL_C(psg_C)
|
||||||
|
);
|
||||||
|
assign psg_snd = {2'b00, psg_A} + {2'b00, psg_B} + {2'b00, psg_C};
|
||||||
|
assign snd_left = fm_snd_left + { 2'b0, psg_snd[9:1],5'd0};
|
||||||
|
assign snd_right = fm_snd_right + { 2'b0, psg_snd[9:1],5'd0};
|
||||||
|
assign dout = addr[0] ? psg_dout : fm_dout;
|
||||||
|
end else begin
|
||||||
|
assign psg_snd = 10'd0;
|
||||||
|
assign snd_left = fm_snd_left;
|
||||||
|
assign snd_right= fm_snd_right;
|
||||||
|
assign psg_dout = 8'd0;
|
||||||
|
assign dout = fm_dout;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef TIMERONLY
|
||||||
|
|
||||||
|
jt12_pg #(.num_ch(num_ch)) u_pg(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
// Channel frequency
|
||||||
|
.fnum_I ( fnum_I ),
|
||||||
|
.block_I ( block_I ),
|
||||||
|
// Operator multiplying
|
||||||
|
.mul_II ( mul_II ),
|
||||||
|
// Operator detuning
|
||||||
|
.dt1_I ( dt1_I ), // same as JT51's DT1
|
||||||
|
// Phase modulation by LFO
|
||||||
|
.lfo_mod ( lfo_mod ),
|
||||||
|
.pms_I ( pms_I ),
|
||||||
|
// phase operation
|
||||||
|
.pg_rst_II ( pg_rst_II ),
|
||||||
|
.pg_stop ( pg_stop ),
|
||||||
|
.keycode_II ( keycode_II ),
|
||||||
|
.phase_VIII ( phase_VIII )
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [9:0] eg_V;
|
||||||
|
|
||||||
|
jt12_eg #(.num_ch(num_ch)) u_eg(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.zero ( zero ),
|
||||||
|
.eg_stop ( eg_stop ),
|
||||||
|
// envelope configuration
|
||||||
|
.keycode_II ( keycode_II ),
|
||||||
|
.arate_I ( ar_I ), // attack rate
|
||||||
|
.rate1_I ( d1r_I ), // decay rate
|
||||||
|
.rate2_I ( d2r_I ), // sustain rate
|
||||||
|
.rrate_I ( rr_I ), // release rate
|
||||||
|
.sl_I ( sl_I ), // sustain level
|
||||||
|
.ks_II ( ks_II ), // key scale
|
||||||
|
// SSG operation
|
||||||
|
.ssg_en_I ( ssg_en_I ),
|
||||||
|
.ssg_eg_I ( ssg_eg_I ),
|
||||||
|
// envelope operation
|
||||||
|
.keyon_I ( keyon_I ),
|
||||||
|
// envelope number
|
||||||
|
.lfo_mod ( lfo_mod ),
|
||||||
|
.tl_IV ( tl_IV ),
|
||||||
|
.ams_IV ( ams_IV ),
|
||||||
|
.amsen_IV ( amsen_IV ),
|
||||||
|
|
||||||
|
.eg_V ( eg_V ),
|
||||||
|
.pg_rst_II ( pg_rst_II )
|
||||||
|
);
|
||||||
|
|
||||||
|
jt12_sh #(.width(10),.stages(4)) u_egpad(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.din ( eg_V ),
|
||||||
|
.drop ( eg_IX )
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [ 8:0] op_result;
|
||||||
|
wire [13:0] full_result;
|
||||||
|
|
||||||
|
jt12_op #(.num_ch(num_ch)) u_op(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.pg_phase_VIII ( phase_VIII ),
|
||||||
|
.eg_atten_IX ( eg_IX ),
|
||||||
|
.fb_II ( fb_II ),
|
||||||
|
|
||||||
|
.test_214 ( 1'b0 ),
|
||||||
|
.s1_enters ( s1_enters ),
|
||||||
|
.s2_enters ( s2_enters ),
|
||||||
|
.s3_enters ( s3_enters ),
|
||||||
|
.s4_enters ( s4_enters ),
|
||||||
|
.xuse_prevprev1 ( xuse_prevprev1),
|
||||||
|
.xuse_internal ( xuse_internal ),
|
||||||
|
.yuse_internal ( yuse_internal ),
|
||||||
|
.xuse_prev2 ( xuse_prev2 ),
|
||||||
|
.yuse_prev1 ( yuse_prev1 ),
|
||||||
|
.yuse_prev2 ( yuse_prev2 ),
|
||||||
|
.zero ( zero ),
|
||||||
|
.op_result ( op_result ),
|
||||||
|
.full_result ( full_result )
|
||||||
|
);
|
||||||
|
|
||||||
|
generate
|
||||||
|
if( use_lr==1 ) begin
|
||||||
|
assign fm_snd_right[3:0] = 4'd0;
|
||||||
|
assign fm_snd_left [3:0] = 4'd0;
|
||||||
|
assign snd_sample = zero;
|
||||||
|
wire signed [8:0] pcm2;
|
||||||
|
|
||||||
|
// interpolate PCM samples with automatic sample rate detection
|
||||||
|
// this feature is not present in original YM2612
|
||||||
|
// this improves PCM sample sound greatly
|
||||||
|
jt12_pcm u_pcm(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.zero ( zero ),
|
||||||
|
.pcm ( pcm ),
|
||||||
|
.pcm_wr ( pcm_wr ),
|
||||||
|
.pcm_resampled ( pcm2 )
|
||||||
|
);
|
||||||
|
|
||||||
|
jt12_acc #(.num_ch(num_ch)) u_acc(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.op_result ( op_result ),
|
||||||
|
.rl ( rl ),
|
||||||
|
// note that the order changes to deal
|
||||||
|
// with the operator pipeline delay
|
||||||
|
.zero ( zero ),
|
||||||
|
.s1_enters ( s2_enters ),
|
||||||
|
.s2_enters ( s1_enters ),
|
||||||
|
.s3_enters ( s4_enters ),
|
||||||
|
.s4_enters ( s3_enters ),
|
||||||
|
.ch6op ( ch6op ),
|
||||||
|
.pcm_en ( pcm_en ), // only enabled for channel 6
|
||||||
|
.pcm ( pcm2 ),
|
||||||
|
.alg ( alg_I ),
|
||||||
|
// combined output
|
||||||
|
.left ( fm_snd_left [15:4] ),
|
||||||
|
.right ( fm_snd_right[15:4] )
|
||||||
|
);
|
||||||
|
end else begin
|
||||||
|
wire signed [15:0] mono_snd;
|
||||||
|
assign fm_snd_left = mono_snd;
|
||||||
|
assign fm_snd_right = mono_snd;
|
||||||
|
assign snd_sample = zero;
|
||||||
|
jt03_acc u_acc(
|
||||||
|
.rst ( rst ),
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.op_result ( full_result ),
|
||||||
|
// note that the order changes to deal
|
||||||
|
// with the operator pipeline delay
|
||||||
|
.s1_enters ( s1_enters ),
|
||||||
|
.s2_enters ( s2_enters ),
|
||||||
|
.s3_enters ( s3_enters ),
|
||||||
|
.s4_enters ( s4_enters ),
|
||||||
|
.alg ( alg_I ),
|
||||||
|
.zero ( zero ),
|
||||||
|
// combined output
|
||||||
|
.snd ( mono_snd )
|
||||||
|
);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
`ifdef SIMULATION
|
||||||
|
/* verilator lint_off PINMISSING */
|
||||||
|
reg [4:0] sep24_cnt;
|
||||||
|
|
||||||
|
wire [9:0] eg_ch0s1, eg_ch1s1, eg_ch2s1, eg_ch3s1, eg_ch4s1, eg_ch5s1,
|
||||||
|
eg_ch0s2, eg_ch1s2, eg_ch2s2, eg_ch3s2, eg_ch4s2, eg_ch5s2,
|
||||||
|
eg_ch0s3, eg_ch1s3, eg_ch2s3, eg_ch3s3, eg_ch4s3, eg_ch5s3,
|
||||||
|
eg_ch0s4, eg_ch1s4, eg_ch2s4, eg_ch3s4, eg_ch4s4, eg_ch5s4;
|
||||||
|
|
||||||
|
always @(posedge clk) if( clk_en )
|
||||||
|
sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
|
||||||
|
|
||||||
|
sep24 #( .width(10), .pos0(5'd0)) egsep
|
||||||
|
(
|
||||||
|
.clk ( clk ),
|
||||||
|
.clk_en ( clk_en ),
|
||||||
|
.mixed ( eg_IX ),
|
||||||
|
.mask ( 24'd0 ),
|
||||||
|
.cnt ( sep24_cnt ),
|
||||||
|
|
||||||
|
.ch0s1 (eg_ch0s1),
|
||||||
|
.ch1s1 (eg_ch1s1),
|
||||||
|
.ch2s1 (eg_ch2s1),
|
||||||
|
.ch3s1 (eg_ch3s1),
|
||||||
|
.ch4s1 (eg_ch4s1),
|
||||||
|
.ch5s1 (eg_ch5s1),
|
||||||
|
|
||||||
|
.ch0s2 (eg_ch0s2),
|
||||||
|
.ch1s2 (eg_ch1s2),
|
||||||
|
.ch2s2 (eg_ch2s2),
|
||||||
|
.ch3s2 (eg_ch3s2),
|
||||||
|
.ch4s2 (eg_ch4s2),
|
||||||
|
.ch5s2 (eg_ch5s2),
|
||||||
|
|
||||||
|
.ch0s3 (eg_ch0s3),
|
||||||
|
.ch1s3 (eg_ch1s3),
|
||||||
|
.ch2s3 (eg_ch2s3),
|
||||||
|
.ch3s3 (eg_ch3s3),
|
||||||
|
.ch4s3 (eg_ch4s3),
|
||||||
|
.ch5s3 (eg_ch5s3),
|
||||||
|
|
||||||
|
.ch0s4 (eg_ch0s4),
|
||||||
|
.ch1s4 (eg_ch1s4),
|
||||||
|
.ch2s4 (eg_ch2s4),
|
||||||
|
.ch3s4 (eg_ch3s4),
|
||||||
|
.ch4s4 (eg_ch4s4),
|
||||||
|
.ch5s4 (eg_ch5s4)
|
||||||
|
);
|
||||||
|
`endif
|
||||||
|
/* verilator lint_on PINMISSING */
|
||||||
|
`endif
|
||||||
|
endmodule
|
64
rtl/sound/jt12/lfo_sh1_lut.hex
Normal file
64
rtl/sound/jt12/lfo_sh1_lut.hex
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
1
|
||||||
|
1
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
0
|
||||||
|
7
|
||||||
|
7
|
||||||
|
1
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
7
|
||||||
|
7
|
||||||
|
1
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
7
|
||||||
|
7
|
||||||
|
1
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
64
rtl/sound/jt12/lfo_sh2_lut.hex
Normal file
64
rtl/sound/jt12/lfo_sh2_lut.hex
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
1
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
1
|
||||||
|
7
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
7
|
||||||
|
7
|
||||||
|
2
|
||||||
|
1
|
@ -1,92 +0,0 @@
|
|||||||
/* This file is part of JT12.
|
|
||||||
|
|
||||||
|
|
||||||
JT12 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.
|
|
||||||
|
|
||||||
JT12 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 JT12. 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: 27-1-2017
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
sinetable[5'd0 ] <= 46'b0001100000100100010001000010101010101001010010;
|
|
||||||
sinetable[5'd1 ] <= 46'b0001100000110100000100000010010001001101000001;
|
|
||||||
sinetable[5'd2 ] <= 46'b0001100000110100000100110010001011001101100000;
|
|
||||||
sinetable[5'd3 ] <= 46'b0001110000010000000000110010110001001101110010;
|
|
||||||
sinetable[5'd4 ] <= 46'b0001110000010000001100000010111010001101101001;
|
|
||||||
sinetable[5'd5 ] <= 46'b0001110000010100001001100010000000101101111010;
|
|
||||||
sinetable[5'd6 ] <= 46'b0001110000010100001101100010010011001101011010;
|
|
||||||
sinetable[5'd7 ] <= 46'b0001110000011100000101010010111000101111111100;
|
|
||||||
sinetable[5'd8 ] <= 46'b0001110000111000000001110010101110001101110111;
|
|
||||||
sinetable[5'd9 ] <= 46'b0001110000111000010100111000011101011010100110;
|
|
||||||
sinetable[5'd10] <= 46'b0001110000111100011000011000111100001001111010;
|
|
||||||
sinetable[5'd11] <= 46'b0001110000111100011100111001101011001001110111;
|
|
||||||
sinetable[5'd12] <= 46'b0100100001010000010001011001001000111010110111;
|
|
||||||
sinetable[5'd13] <= 46'b0100100001010100010001001001110001111100101010;
|
|
||||||
sinetable[5'd14] <= 46'b0100100001010100010101101101111110100101000110;
|
|
||||||
sinetable[5'd15] <= 46'b0100100011100000001000011001010110101101111001;
|
|
||||||
sinetable[5'd16] <= 46'b0100100011100100001000101011100101001011101111;
|
|
||||||
sinetable[5'd17] <= 46'b0100100011101100000111011010000001011010110001;
|
|
||||||
sinetable[5'd18] <= 46'b0100110011001000000111101010000010111010111111;
|
|
||||||
sinetable[5'd19] <= 46'b0100110011001100001011011110101110110110000001;
|
|
||||||
sinetable[5'd20] <= 46'b0100110011101000011010111011001010001101110001;
|
|
||||||
sinetable[5'd21] <= 46'b0100110011101101011010110101111001010100001111;
|
|
||||||
sinetable[5'd22] <= 46'b0111000010000001010111000101010101010110010111;
|
|
||||||
sinetable[5'd23] <= 46'b0111000010000101010111110111110101010010111011;
|
|
||||||
sinetable[5'd24] <= 46'b0111000010110101101000101100001000010000011001;
|
|
||||||
sinetable[5'd25] <= 46'b0111010010011001100100011110100100010010010010;
|
|
||||||
sinetable[5'd26] <= 46'b0111010010111010100101100101000000110100100011;
|
|
||||||
sinetable[5'd27] <= 46'b1010000010011010101101011101100001110010011010;
|
|
||||||
sinetable[5'd28] <= 46'b1010000010111111111100100111010100010000111001;
|
|
||||||
sinetable[5'd29] <= 46'b1010010111110100110010001100111001010110100000;
|
|
||||||
sinetable[5'd30] <= 46'b1011010111010011111011011110000100110010100001;
|
|
||||||
sinetable[5'd31] <= 46'b1110011011110001111011100111100001110110100111;
|
|
||||||
|
|
||||||
explut_jt51[0] <= 45'b111110101011010110001011010000010010111011011;
|
|
||||||
explut_jt51[1] <= 45'b111101010011010101000011001100101110110101011;
|
|
||||||
explut_jt51[2] <= 45'b111011111011010011110111001000110010101110011;
|
|
||||||
explut_jt51[3] <= 45'b111010100101010010101111000100110010101000011;
|
|
||||||
explut_jt51[4] <= 45'b111001001101010001100111000000110010100001011;
|
|
||||||
explut_jt51[5] <= 45'b110111111011010000011110111101010010011011011;
|
|
||||||
explut_jt51[6] <= 45'b110110100011001111010110111001010010010100100;
|
|
||||||
explut_jt51[7] <= 45'b110101001011001110001110110101110010001110011;
|
|
||||||
explut_jt51[8] <= 45'b110011111011001101000110110001110010001000011;
|
|
||||||
explut_jt51[9] <= 45'b110010100011001011111110101110010010000010011;
|
|
||||||
explut_jt51[10] <= 45'b110001010011001010111010101010010001111011011;
|
|
||||||
explut_jt51[11] <= 45'b101111111011001001110010100110110001110101011;
|
|
||||||
explut_jt51[12] <= 45'b101110101011001000101010100011001101101111011;
|
|
||||||
explut_jt51[13] <= 45'b101101010101000111100110011111010001101001011;
|
|
||||||
explut_jt51[14] <= 45'b101100000011000110100010011011110001100011011;
|
|
||||||
explut_jt51[15] <= 45'b101010110011000101011110011000010001011101011;
|
|
||||||
explut_jt51[16] <= 45'b101001100011000100011010010100101101010111011;
|
|
||||||
explut_jt51[17] <= 45'b101000010011000011010010010001001101010001011;
|
|
||||||
explut_jt51[18] <= 45'b100111000011000010010010001101101101001011011;
|
|
||||||
explut_jt51[19] <= 45'b100101110011000001001110001010001101000101011;
|
|
||||||
explut_jt51[20] <= 45'b100100100011000000001010000110010000111111011;
|
|
||||||
explut_jt51[21] <= 45'b100011010010111111001010000011001100111001011;
|
|
||||||
explut_jt51[22] <= 45'b100010000010111110000101111111101100110011011;
|
|
||||||
explut_jt51[23] <= 45'b100000110010111101000001111100001100101101011;
|
|
||||||
explut_jt51[24] <= 45'b011111101010111100000001111000101100101000010;
|
|
||||||
explut_jt51[25] <= 45'b011110011010111011000001110101001100100010011;
|
|
||||||
explut_jt51[26] <= 45'b011101001010111010000001110001110000011100011;
|
|
||||||
explut_jt51[27] <= 45'b011100000010111001000001101110010000010110011;
|
|
||||||
explut_jt51[28] <= 45'b011010110010111000000001101011001100010001011;
|
|
||||||
explut_jt51[29] <= 45'b011001101010110111000001100111101100001011011;
|
|
||||||
explut_jt51[30] <= 45'b011000100000110110000001100100010000000110010;
|
|
||||||
explut_jt51[31] <= 45'b010111010010110101000001100001001100000000011;
|
|
||||||
end
|
|
@ -23,115 +23,157 @@
|
|||||||
module turbosound
|
module turbosound
|
||||||
(
|
(
|
||||||
input RESET, // Chip RESET (set all Registers to '0', active high)
|
input RESET, // Chip RESET (set all Registers to '0', active high)
|
||||||
|
|
||||||
input CLK, // Global clock
|
input CLK, // Global clock
|
||||||
input CE_CPU, // CPU Clock enable
|
input CE, // YM2203 Master Clock enable
|
||||||
input CE_YM, // YM2203 Master Clock enable x2 (due to YM2612 model!)
|
|
||||||
input BDIR, // Bus Direction (0 - read , 1 - write)
|
input BDIR, // Bus Direction (0 - read , 1 - write)
|
||||||
input BC, // Bus control
|
input BC, // Bus control
|
||||||
input [7:0] DI, // Data In
|
input [7:0] DI, // Data In
|
||||||
output [7:0] DO, // Data Out
|
output [7:0] DO, // Data Out
|
||||||
|
|
||||||
output [11:0] CHANNEL_L, // Output channel L
|
output [11:0] CHANNEL_L, // Output channel L
|
||||||
output [11:0] CHANNEL_R, // Output channel R
|
output [11:0] CHANNEL_R // Output channel R
|
||||||
output ACTIVE
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
reg RESET_s;
|
||||||
|
reg BDIR_s;
|
||||||
|
reg BC_s;
|
||||||
|
reg [7:0] DI_s;
|
||||||
|
|
||||||
|
always_ff @(posedge CLK) begin
|
||||||
|
reg RESET_d;
|
||||||
|
reg BDIR_d;
|
||||||
|
reg BC_d;
|
||||||
|
reg [7:0] DI_d;
|
||||||
|
|
||||||
|
RESET_d <= RESET;
|
||||||
|
BDIR_d <= BDIR;
|
||||||
|
BC_d <= BC;
|
||||||
|
DI_d <= DI;
|
||||||
|
|
||||||
|
RESET_s <= RESET_d;
|
||||||
|
BDIR_s <= BDIR_d;
|
||||||
|
BC_s <= BC_d;
|
||||||
|
DI_s <= DI_d;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// AY1 selected by default
|
// AY1 selected by default
|
||||||
reg ay_select = 1;
|
reg ay_select = 1;
|
||||||
reg stat_sel = 1;
|
reg stat_sel = 1;
|
||||||
reg fm_ena = 0;
|
reg fm_ena = 0;
|
||||||
|
reg ym_wr = 0;
|
||||||
|
reg [7:0] ym_di;
|
||||||
|
|
||||||
always_ff @(posedge CLK or posedge RESET) begin
|
always_ff @(posedge CLK or posedge RESET_s) begin
|
||||||
if (RESET) begin
|
reg old_BDIR = 0;
|
||||||
|
reg ym_acc = 0;
|
||||||
|
|
||||||
|
if (RESET_s) begin
|
||||||
ay_select <= 1;
|
ay_select <= 1;
|
||||||
stat_sel <= 1;
|
stat_sel <= 1;
|
||||||
fm_ena <= 0;
|
fm_ena <= 0;
|
||||||
|
ym_acc <= 0;
|
||||||
|
ym_wr <= 0;
|
||||||
|
old_BDIR <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
ym_wr <= 0;
|
||||||
|
old_BDIR <= BDIR_s;
|
||||||
|
if (~old_BDIR & BDIR_s) begin
|
||||||
|
if(BC_s & &DI_s[7:3]) begin
|
||||||
|
ay_select <= DI_s[0];
|
||||||
|
stat_sel <= DI_s[1];
|
||||||
|
fm_ena <= ~DI_s[2];
|
||||||
|
ym_acc <= 0;
|
||||||
|
end
|
||||||
|
else if(BC_s) begin
|
||||||
|
ym_acc <= !DI_s[7:4] || fm_ena;
|
||||||
|
ym_wr <= !DI_s[7:4] || fm_ena;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
ym_wr <= ym_acc;
|
||||||
|
end
|
||||||
|
ym_di <= DI_s;
|
||||||
end
|
end
|
||||||
else if (BDIR & BC & &DI[7:3]) begin
|
|
||||||
ay_select <= DI[0];
|
|
||||||
stat_sel <= DI[1];
|
|
||||||
fm_ena <= ~DI[2];
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wire [7:0] psg_ch_a_0;
|
wire [7:0] psg_ch_a_0;
|
||||||
wire [7:0] psg_ch_b_0;
|
wire [7:0] psg_ch_b_0;
|
||||||
wire [7:0] psg_ch_c_0;
|
wire [7:0] psg_ch_c_0;
|
||||||
wire [10:0] opn_0;
|
wire [15:0] opn_0;
|
||||||
wire [7:0] DO_0;
|
wire [7:0] DO_0;
|
||||||
|
|
||||||
wire WE_0 = ~ay_select & BDIR;
|
jt03 ym2203_0
|
||||||
wire ay0_playing;
|
|
||||||
|
|
||||||
ym2203 ym2203_0
|
|
||||||
(
|
(
|
||||||
.RESET(RESET),
|
.rst(RESET_s),
|
||||||
.CLK(CLK),
|
.clk(CLK),
|
||||||
.CE_CPU(CE_CPU),
|
.cen(CE),
|
||||||
.CE_YM(CE_YM),
|
.din(ym_di),
|
||||||
|
.addr((BDIR_s|ym_wr) ? ~BC_s : stat_sel),
|
||||||
|
.cs_n(ay_select),
|
||||||
|
.wr_n(~ym_wr),
|
||||||
|
.dout(DO_0),
|
||||||
|
|
||||||
.A0(WE_0 ? ~BC : stat_sel),
|
.psg_A(psg_ch_a_0),
|
||||||
.WE(WE_0),
|
.psg_B(psg_ch_b_0),
|
||||||
.DI(DI),
|
.psg_C(psg_ch_c_0),
|
||||||
.DO(DO_0),
|
|
||||||
|
|
||||||
.CHANNEL_A(psg_ch_a_0),
|
.fm_snd(opn_0)
|
||||||
.CHANNEL_B(psg_ch_b_0),
|
|
||||||
.CHANNEL_C(psg_ch_c_0),
|
|
||||||
.CHANNEL_FM(opn_0),
|
|
||||||
|
|
||||||
.PSG_ACTIVE(ay0_playing),
|
|
||||||
.FM_ENA(fm_ena)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [7:0] psg_ch_a_1;
|
wire [7:0] psg_ch_a_1;
|
||||||
wire [7:0] psg_ch_b_1;
|
wire [7:0] psg_ch_b_1;
|
||||||
wire [7:0] psg_ch_c_1;
|
wire [7:0] psg_ch_c_1;
|
||||||
wire [10:0] opn_1;
|
wire [15:0] opn_1;
|
||||||
wire [7:0] DO_1;
|
wire [7:0] DO_1;
|
||||||
|
|
||||||
wire WE_1 = ay_select & BDIR;
|
jt03 ym2203_1
|
||||||
wire ay1_playing;
|
|
||||||
|
|
||||||
ym2203 ym2203_1
|
|
||||||
(
|
(
|
||||||
.RESET(RESET),
|
.rst(RESET_s),
|
||||||
.CLK(CLK),
|
.clk(CLK),
|
||||||
.CE_CPU(CE_CPU),
|
.cen(CE),
|
||||||
.CE_YM(CE_YM),
|
.din(ym_di),
|
||||||
|
.addr((BDIR_s|ym_wr) ? ~BC_s : stat_sel),
|
||||||
|
.cs_n(~ay_select),
|
||||||
|
.wr_n(~ym_wr),
|
||||||
|
.dout(DO_1),
|
||||||
|
|
||||||
.A0(WE_1 ? ~BC : stat_sel),
|
.psg_A(psg_ch_a_1),
|
||||||
.WE(WE_1),
|
.psg_B(psg_ch_b_1),
|
||||||
.DI(DI),
|
.psg_C(psg_ch_c_1),
|
||||||
.DO(DO_1),
|
|
||||||
|
|
||||||
.CHANNEL_A(psg_ch_a_1),
|
.fm_snd(opn_1)
|
||||||
.CHANNEL_B(psg_ch_b_1),
|
|
||||||
.CHANNEL_C(psg_ch_c_1),
|
|
||||||
.CHANNEL_FM(opn_1),
|
|
||||||
|
|
||||||
.PSG_ACTIVE(ay1_playing),
|
|
||||||
.FM_ENA(fm_ena)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assign DO = ay_select ? DO_1 : DO_0;
|
assign DO = ay_select ? DO_1 : DO_0;
|
||||||
assign ACTIVE = ay0_playing | ay1_playing | fm_ena;
|
|
||||||
|
|
||||||
// Mix channel signals from both AY/YM chips (extending to 9 bits width to prevent clipping)
|
reg [8:0] sum_ch_a,sum_ch_b,sum_ch_c;
|
||||||
wire [8:0] sum_ch_a = { 1'b0, psg_ch_a_1 } + { 1'b0, psg_ch_a_0 };
|
reg [7:0] psg_a,psg_b,psg_c;
|
||||||
wire [8:0] sum_ch_b = { 1'b0, psg_ch_b_1 } + { 1'b0, psg_ch_b_0 };
|
reg [11:0] psg_l,psg_r,opn_s;
|
||||||
wire [8:0] sum_ch_c = { 1'b0, psg_ch_c_1 } + { 1'b0, psg_ch_c_0 };
|
reg [11:0] ch_l, ch_r;
|
||||||
|
|
||||||
// Control output channels (Only AY_1 plays if not in TurboSound mode)
|
always @(posedge CLK) begin
|
||||||
wire [7:0] psg_a = ~ay0_playing ? psg_ch_a_1 : sum_ch_a[8:1];
|
|
||||||
wire [7:0] psg_b = ~ay0_playing ? psg_ch_b_1 : sum_ch_b[8:1];
|
|
||||||
wire [7:0] psg_c = ~ay0_playing ? psg_ch_c_1 : sum_ch_c[8:1];
|
|
||||||
|
|
||||||
wire signed [11:0] psg_l = {3'b000, psg_a, 1'd0} + {4'b0000, psg_b};
|
sum_ch_a <= { 1'b0, psg_ch_a_1 } + { 1'b0, psg_ch_a_0 };
|
||||||
wire signed [11:0] psg_r = {3'b000, psg_c, 1'd0} + {4'b0000, psg_b};
|
sum_ch_b <= { 1'b0, psg_ch_b_1 } + { 1'b0, psg_ch_b_0 };
|
||||||
wire signed [11:0] opn_s = {{2{opn_0[10]}}, opn_0[10:1]} + {{2{opn_1[10]}}, opn_1[10:1]};
|
sum_ch_c <= { 1'b0, psg_ch_c_1 } + { 1'b0, psg_ch_c_0 };
|
||||||
|
|
||||||
assign CHANNEL_L = fm_ena ? opn_s + psg_l : psg_l;
|
psg_a <= sum_ch_a[8] ? 8'hFF : sum_ch_a[7:0];
|
||||||
assign CHANNEL_R = fm_ena ? opn_s + psg_r : psg_r;
|
psg_b <= sum_ch_b[8] ? 8'hFF : sum_ch_b[7:0];
|
||||||
|
psg_c <= sum_ch_c[8] ? 8'hFF : sum_ch_c[7:0];
|
||||||
|
|
||||||
|
psg_l <= {3'b000, psg_a, 1'd0} + {4'b0000, psg_b};
|
||||||
|
psg_r <= {3'b000, psg_c, 1'd0} + {4'b0000, psg_b};
|
||||||
|
opn_s <= {{2{opn_0[15]}}, opn_0[15:6]} + {{2{opn_1[15]}}, opn_1[15:6]};
|
||||||
|
|
||||||
|
ch_l <= fm_ena ? $signed(opn_s) + $signed(psg_l) : $signed(psg_l);
|
||||||
|
ch_r <= fm_ena ? $signed(opn_s) + $signed(psg_r) : $signed(psg_r);
|
||||||
|
end
|
||||||
|
|
||||||
|
assign CHANNEL_L = ch_l;
|
||||||
|
assign CHANNEL_R = ch_r;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) MikeJ - Jan 2005
|
// Copyright (c) MikeJ - Jan 2005
|
||||||
// Copyright (c) 2016-2018 Sorgelig
|
// Copyright (c) 2016-2019 Sorgelig
|
||||||
//
|
//
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
@ -151,18 +151,13 @@ always @(posedge CLK) begin
|
|||||||
|
|
||||||
if(CE) begin
|
if(CE) begin
|
||||||
if (ena_div_noise) begin
|
if (ena_div_noise) begin
|
||||||
if(ymreg[6][4:0]) begin
|
if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
|
||||||
if (noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
|
|
||||||
noise_gen_cnt <= 0;
|
noise_gen_cnt <= 0;
|
||||||
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
|
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
|
||||||
end else begin
|
end else begin
|
||||||
noise_gen_cnt <= noise_gen_cnt + 1'd1;
|
noise_gen_cnt <= noise_gen_cnt + 1'd1;
|
||||||
end
|
end
|
||||||
noise_gen_op <= {3{poly17[0]}};
|
noise_gen_op <= {3{poly17[0]}};
|
||||||
end else begin
|
|
||||||
noise_gen_op <= ymreg[7][5:3];
|
|
||||||
noise_gen_cnt <= 0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -192,7 +187,7 @@ always @(posedge CLK) begin
|
|||||||
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
|
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
tone_gen_op[i] <= ymreg[7][i];
|
tone_gen_op[i] <= ~ymreg[7][i];
|
||||||
tone_gen_cnt[i] <= 0;
|
tone_gen_cnt[i] <= 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,130 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
// YM2203 wrapper
|
|
||||||
// Copyright (C) 2018 Sorgelig
|
|
||||||
//
|
|
||||||
// This 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 2 of the License, or (at your option)
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// This 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
module ym2203
|
|
||||||
(
|
|
||||||
input RESET,
|
|
||||||
input CLK, // Global clock
|
|
||||||
input CE_CPU, // CPU Clock enable
|
|
||||||
input CE_YM, // YM2203 Master Clock enable x2 (due to YM2612 model!)
|
|
||||||
|
|
||||||
input A0, // 0 - register number/read FM, 1 - data/read PSG
|
|
||||||
input WE, // 0 - read , 1 - write
|
|
||||||
input [7:0] DI, // Data In
|
|
||||||
output [7:0] DO, // Data Out
|
|
||||||
|
|
||||||
output [7:0] CHANNEL_A, // PSG Output channel A
|
|
||||||
output [7:0] CHANNEL_B, // PSG Output channel B
|
|
||||||
output [7:0] CHANNEL_C, // PSG Output channel C
|
|
||||||
output [10:0] CHANNEL_FM,// FM Output channel
|
|
||||||
|
|
||||||
output PSG_ACTIVE,
|
|
||||||
input FM_ENA
|
|
||||||
);
|
|
||||||
|
|
||||||
reg [7:0] ymreg;
|
|
||||||
reg [1:0] pres;
|
|
||||||
|
|
||||||
always @(posedge CLK) begin
|
|
||||||
|
|
||||||
if(RESET) pres <= 2;
|
|
||||||
else if(CE_CPU & WE) begin
|
|
||||||
if(FM_ENA) begin
|
|
||||||
if(~A0) ymreg <= DI;
|
|
||||||
else begin
|
|
||||||
case(ymreg)
|
|
||||||
'h2d: pres[1] <= 1;
|
|
||||||
'h2e: pres[0] <= 1;
|
|
||||||
'h2f: pres <= 0;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
wire [2:0] opn_tbl[4] = '{1,1,5,2};
|
|
||||||
wire [2:0] opn_pres = opn_tbl[pres];
|
|
||||||
|
|
||||||
wire [2:0] psg_tbl[4] = '{0,0,3,1};
|
|
||||||
wire [2:0] psg_pres = psg_tbl[pres];
|
|
||||||
|
|
||||||
reg ce_psg_pre, ce_opn_pre;
|
|
||||||
always @(posedge CLK) begin
|
|
||||||
reg [2:0] div_psg, div_opn;
|
|
||||||
|
|
||||||
{ce_opn_pre, ce_psg_pre} <= 0;
|
|
||||||
|
|
||||||
if(RESET) {div_opn, div_psg} <= 0;
|
|
||||||
else if (CE_YM) begin
|
|
||||||
div_opn <= div_opn + 1'd1;
|
|
||||||
if(div_opn >= opn_pres) div_opn <= 0;
|
|
||||||
ce_opn_pre <= !div_opn;
|
|
||||||
|
|
||||||
div_psg <= div_psg + 1'd1;
|
|
||||||
if(div_psg >= psg_pres) div_psg <= 0;
|
|
||||||
ce_psg_pre <= !div_psg;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reg ce_opn, ce_psg;
|
|
||||||
always @(negedge CLK) {ce_opn, ce_psg} <= {ce_opn_pre, ce_psg_pre};
|
|
||||||
|
|
||||||
wire [5:0] psg_active;
|
|
||||||
wire [7:0] psg_dout;
|
|
||||||
ym2149 ym2149
|
|
||||||
(
|
|
||||||
.CLK(CLK),
|
|
||||||
.CE(ce_psg),
|
|
||||||
.RESET(RESET),
|
|
||||||
.BDIR(WE),
|
|
||||||
.BC(~A0 | ~WE),
|
|
||||||
.DI(DI),
|
|
||||||
.DO(psg_dout),
|
|
||||||
.CHANNEL_A(CHANNEL_A),
|
|
||||||
.CHANNEL_B(CHANNEL_B),
|
|
||||||
.CHANNEL_C(CHANNEL_C),
|
|
||||||
.ACTIVE(psg_active),
|
|
||||||
.SEL(1'b0),
|
|
||||||
.MODE(1'b0)
|
|
||||||
);
|
|
||||||
|
|
||||||
wire [7:0] opn_dout;
|
|
||||||
wire [11:0] opn_audio;
|
|
||||||
jt12 jt12
|
|
||||||
(
|
|
||||||
.rst(RESET),
|
|
||||||
|
|
||||||
.cpu_clk(CLK & CE_CPU),
|
|
||||||
.cpu_din(DI),
|
|
||||||
.cpu_dout(opn_dout),
|
|
||||||
.cpu_addr({1'b0,A0}),
|
|
||||||
.cpu_cs_n(~FM_ENA),
|
|
||||||
.cpu_wr_n(~WE),
|
|
||||||
|
|
||||||
.syn_clk(CLK & ce_opn),
|
|
||||||
.cpu_limiter_en(1'b1),
|
|
||||||
.syn_snd_right(opn_audio)
|
|
||||||
);
|
|
||||||
|
|
||||||
assign DO = A0 ? psg_dout : opn_dout;
|
|
||||||
assign PSG_ACTIVE = |psg_active;
|
|
||||||
assign CHANNEL_FM = opn_audio[10:0];
|
|
||||||
|
|
||||||
endmodule
|
|
@ -794,7 +794,7 @@ soundrive SE10
|
|||||||
// Turbosound FM
|
// Turbosound FM
|
||||||
reg ce_ym;
|
reg ce_ym;
|
||||||
always @(posedge clk_28mhz) begin
|
always @(posedge clk_28mhz) begin
|
||||||
reg [1:0] div;
|
reg [2:0] div;
|
||||||
|
|
||||||
div <= div + 1'd1;
|
div <= div + 1'd1;
|
||||||
ce_ym <= !div;
|
ce_ym <= !div;
|
||||||
@ -811,8 +811,7 @@ turbosound SE12
|
|||||||
.RESET(reset),
|
.RESET(reset),
|
||||||
|
|
||||||
.CLK(clk_28mhz),
|
.CLK(clk_28mhz),
|
||||||
.CE_CPU(zpos),
|
.CE(ce_ym),
|
||||||
.CE_YM(ce_ym),
|
|
||||||
.BDIR(ts_we),
|
.BDIR(ts_we),
|
||||||
.BC(cpu_a_bus[14]),
|
.BC(cpu_a_bus[14]),
|
||||||
.DI(cpu_do_bus),
|
.DI(cpu_do_bus),
|
||||||
|
Reference in New Issue
Block a user