diff --git a/files.qip b/files.qip
index 075047b..3b45528 100644
--- a/files.qip
+++ b/files.qip
@@ -12,7 +12,6 @@ set_global_assignment -name VERILOG_FILE rtl/common/zclock.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 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/turbosound.sv
set_global_assignment -name VERILOG_FILE rtl/sound/gs.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sound/saa1099.sv
diff --git a/rtl/sound/jt12/jt03.qip b/rtl/sound/jt12/jt03.qip
index c8a0497..762da8e 100644
--- a/rtl/sound/jt12/jt03.qip
+++ b/rtl/sound/jt12/jt03.qip
@@ -1,34 +1,36 @@
-set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03.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_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_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_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_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_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_op.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_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_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_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_timers.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt03.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_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_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_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_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_op.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_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_ch.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_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_timers.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt12_dout.v ]
+set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) ../jt49/jt49.qip ]
diff --git a/rtl/sound/jt12/jt03.v b/rtl/sound/jt12/jt03.v
index 9b3212a..8092c9e 100644
--- a/rtl/sound/jt12/jt03.v
+++ b/rtl/sound/jt12/jt03.v
@@ -1,6 +1,6 @@
/* 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
@@ -21,31 +21,43 @@
// 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 cen, // optional clock enable, if 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,
+ // I/O pins used by YM2203 embedded YM2149 chip
+ input [7:0] IOA_in,
+ input [7:0] IOB_in,
+ output [7:0] IOA_out,
+ output [7:0] IOB_out,
+ output IOA_oe,
+ output IOB_oe,
// 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 [ 9:0] psg_snd,
output signed [15:0] snd,
- output snd_sample
+ output snd_sample,
+ // Debug
+ //input [ 7:0] debug_bus,
+ output [ 7:0] debug_view
);
-jt12_top #(.use_lfo(0),.use_ssg(1), .num_ch(3), .use_pcm(0), .use_lr(0))
+parameter YM2203_LUMPED=0; // set to 1 if all PSG outputs are shorted together without any resistor
+
+jt12_top #(
+ .use_lfo(0),.use_ssg(1), .num_ch(3), .use_pcm(0), .use_adpcm(0), .mask_div(0),
+ .YM2203_LUMPED(YM2203_LUMPED) )
u_jt12(
.rst ( rst ), // rst should be at least 6 clk&cen cycles long
.clk ( clk ), // CPU clock
@@ -54,20 +66,45 @@ u_jt12(
.addr ( {1'b0, addr} ),
.cs_n ( cs_n ),
.wr_n ( wr_n ),
-
+ .ch_enable ( 6'd0 ),
+
.dout ( dout ),
.irq_n ( irq_n ),
+ // YM2203 I/O pins
+ .IOA_in ( IOA_in ),
+ .IOB_in ( IOB_in ),
+ .IOA_out ( IOA_out ),
+ .IOB_out ( IOB_out ),
+ .IOA_oe ( IOA_oe ),
+ .IOB_oe ( IOB_oe ),
+ // Unused ADPCM pins
+ .en_hifi_pcm ( 1'b0 ), // used only on YM2612 mode
+ .adpcma_addr ( ), // real hardware has 10 pins multiplexed through RMPX pin
+ .adpcma_bank ( ),
+ .adpcma_roe_n ( ), // ADPCM-A ROM output enable
+ .adpcma_data ( 8'd0 ), // Data from RAM
+ .adpcmb_data ( 8'd0 ),
+ .adpcmb_addr ( ), // real hardware has 12 pins multiplexed through PMPX pin
+ .adpcmb_roe_n ( ), // ADPCM-B ROM output enable
// Separated output
.psg_A ( psg_A ),
.psg_B ( psg_B ),
.psg_C ( psg_C ),
- .psg_snd ( psg_snd ),
+ .psg_snd ( psg_snd ),
.fm_snd_left ( fm_snd ),
.fm_snd_right (),
+ .adpcmA_l (),
+ .adpcmA_r (),
+ .adpcmB_l (),
+ .adpcmB_r (),
.snd_right ( snd ),
.snd_left (),
- .snd_sample ( snd_sample )
+ .snd_sample ( snd_sample ),
+
+ //.debug_bus ( debug_bus ),
+ .debug_bus ( 8'd0 ),
+ .debug_view ( debug_view )
);
-endmodule // jt03
\ No newline at end of file
+endmodule // jt03
diff --git a/rtl/sound/jt12/jt03_acc.v b/rtl/sound/jt12/jt03_acc.v
index 8d9805d..89dae34 100644
--- a/rtl/sound/jt12/jt03_acc.v
+++ b/rtl/sound/jt12/jt03_acc.v
@@ -20,18 +20,20 @@
*/
-`timescale 1ns / 1ps
-/* Use for YM2203
- no left/right channels
- full operator resolution
- clamped to maximum output of signed 16 bits */
+// Use for YM2203
+// no left/right channels
+// full operator resolution
+// clamped to maximum output of signed 16 bits
+// This version does not clamp each channel individually
+// That does not correspond to real hardware behaviour. I should
+// change it.
module jt03_acc
(
input rst,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input signed [13:0] op_result,
input s1_enters,
input s2_enters,
@@ -54,6 +56,11 @@ always @(*) begin
endcase
end
+// real YM2608 drops the op_result LSB, resulting in a 13-bit accumulator
+// but in YM2203, a 13-bit acc for 3 channels only requires 15 bits
+// and YM3014 has a 16-bit dynamic range.
+// I am leaving the LSB and scaling the output voltage accordingly. This
+// should result in less quantification noise.
jt12_single_acc #(.win(14),.wout(16)) u_mono(
.clk ( clk ),
.clk_en ( clk_en ),
diff --git a/rtl/sound/jt12/jt12.v b/rtl/sound/jt12/jt12.v
deleted file mode 100644
index b3b553e..0000000
--- a/rtl/sound/jt12/jt12.v
+++ /dev/null
@@ -1,65 +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 .
-
- Author: Jose Tejada Gomez. Twitter: @topapate
- Version: 1.0
- Date: 27-12-2018
-
-*/
-
-// Wrapper to output only combined channels. Defaults to YM2612 mode.
-
-module jt12 (
- 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,
- // combined output
- output signed [15:0] snd_right,
- output signed [15:0] snd_left,
- output snd_sample
-);
-
-jt12_top 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 ( addr ),
- .cs_n ( cs_n ),
- .wr_n ( wr_n ),
-
- .dout ( dout ),
- .irq_n ( irq_n ),
- // Separated output
- .psg_A (),
- .psg_B (),
- .psg_C (),
- .fm_snd_left (),
- .fm_snd_right (),
- // combined output
- .psg_snd (),
- .snd_right ( snd_right ), // FM+PSG
- .snd_left ( snd_left ), // FM+PSG
- .snd_sample ( snd_sample )
-);
-endmodule // jt03
\ No newline at end of file
diff --git a/rtl/sound/jt12/jt12.vhd b/rtl/sound/jt12/jt12.vhd
index 58fa856..d2e4025 100644
--- a/rtl/sound/jt12/jt12.vhd
+++ b/rtl/sound/jt12/jt12.vhd
@@ -16,6 +16,7 @@ port
dout : out std_logic_vector(7 downto 0);
irq_n : out std_logic;
+ en_hifi_pcm: in std_logic; -- set high to use interpolation on PCM samples
-- combined output
snd_right : out std_logic_vector(15 downto 0); -- signed
diff --git a/rtl/sound/jt12/jt12_acc.v b/rtl/sound/jt12/jt12_acc.v
deleted file mode 100644
index d0fc9fe..0000000
--- a/rtl/sound/jt12/jt12_acc.v
+++ /dev/null
@@ -1,109 +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 .
-
- Author: Jose Tejada Gomez. Twitter: @topapate
- Version: 1.0
- Date: 27-1-2017
-
- Each channel can use the full range of the DAC as they do not
- 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(
- input rst,
- input clk,
- input clk_en,
- input signed [8:0] op_result,
- input [ 1:0] rl,
- input zero,
- input s1_enters,
- input s2_enters,
- input s3_enters,
- input s4_enters,
- input ch6op,
- input [2:0] alg,
- input pcm_en, // only enabled for channel 6
- input signed [8:0] pcm,
- // combined output
- output reg signed [11:0] left,
- output reg signed [11:0] right
-);
-
-parameter num_ch=6;
-
-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
-
-reg pcm_sum;
-
-always @(posedge clk) if(clk_en)
- if( zero ) pcm_sum <= 1'b1;
- else if( ch6op ) pcm_sum <= 1'b0;
-
-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;
-
-// Continuous output
-wire signed [11:0] pre_left, pre_right;
-jt12_single_acc #(.win(9),.wout(12)) u_left(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .op_result ( acc_input ),
- .sum_en ( sum_or_pcm & left_en ),
- .zero ( zero ),
- .snd ( pre_left )
-);
-
-jt12_single_acc #(.win(9),.wout(12)) u_right(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .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
diff --git a/rtl/sound/jt12/jt12_csr.v b/rtl/sound/jt12/jt12_csr.v
index b258a55..74e56ab 100644
--- a/rtl/sound/jt12/jt12_csr.v
+++ b/rtl/sound/jt12/jt12_csr.v
@@ -23,7 +23,7 @@
module jt12_csr( // Circular Shift Register + input mux
input rst,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input [ 7:0] din,
input [43:0] shift_in,
output [43:0] shift_out,
diff --git a/rtl/sound/jt12/jt12_div.v b/rtl/sound/jt12/jt12_div.v
index e06bfda..4b58315 100644
--- a/rtl/sound/jt12/jt12_div.v
+++ b/rtl/sound/jt12/jt12_div.v
@@ -18,54 +18,102 @@
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
+ input cen /* synthesis direct_enable */,
+ input [1:0] div_setting,
+ output reg clk_en, // after prescaler
+ output reg clk_en_2, // cen divided by 2
+ output reg clk_en_ssg,
+ output reg clk_en_666, // 666 kHz
+ output reg clk_en_111, // 111 kHz
+ output reg clk_en_55 // 55 kHz
);
-parameter use_ssg=0, num_ch;
+parameter use_ssg=0;
-reg [3:0] opn_pres, opn_cnt;
-reg [2:0] ssg_pres, ssg_cnt;
-reg cen_int, cen_ssg_int;
+reg [3:0] opn_pres, opn_cnt=4'd0;
+reg [2:0] ssg_pres, ssg_cnt=3'd0;
+reg [4:0] adpcm_cnt666 = 5'd0;
+reg [2:0] adpcm_cnt111 = 3'd0, adpcm_cnt55=3'd0;
+reg cen_int, cen_ssg_int, cen_adpcm_int, cen_adpcm3_int;
-always @(*)
- if( num_ch==6 ) begin
- opn_pres = 4'd5;
- ssg_pres = 3'd3; // unused, really
- end
- else
+// prescaler values for FM
+// reset: 1/3
+// sel1/sel2
+// 0 0 1/3
+// 0 1 1/2
+// 1 0 1/6
+// 1 1 1/2
+//
+// According to YM2608 document
+// FM SSG div[1:0]
+// reset value 1/6 1/4 10
+// 2D 1/6 1/4 10 | 10
+// 2D,2E 1/3 1/2 11 | 01
+// 2F 1/2 1/1 00 & 00
+//
+
+always @(*) begin
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
+ 2'b0?: begin // FM 1/2 - SSG 1/1
+ opn_pres = 4'd2-4'd1;
+ ssg_pres = 3'd0;
+ end
+ 2'b10: begin // FM 1/6 - SSG 1/4 (reset value. Fixed for YM2610)
+ opn_pres = 4'd6-4'd1;
+ ssg_pres = 3'd3;
+ end
+ 2'b11: begin // FM 1/3 - SSG 1/2
+ opn_pres = 4'd3-4'd1;
+ ssg_pres = 3'd1;
+ end
endcase // div_setting
+end
+`ifdef SIMULATION
+initial clk_en_666 = 1'b0;
+`endif
+
+reg cen_55_int;
+reg [1:0] div2=2'b0;
always @(negedge clk) begin
- cen_int <= opn_cnt == 4'd0;
- cen_ssg_int <= ssg_cnt == 3'd0;
+ cen_int <= opn_cnt == 4'd0;
+ cen_ssg_int <= ssg_cnt == 3'd0;
+ cen_adpcm_int <= adpcm_cnt666 == 5'd0;
+ cen_adpcm3_int <= adpcm_cnt111 == 3'd0;
+ cen_55_int <= adpcm_cnt55 == 3'd0;
`ifdef FASTDIV
- // always enabled for fast sims (use with GYM output, timer will not work well)
- clk_en <= 1'b1;
+ // always enabled for fast sims (use with GYM output, the timers will not work well)
+ clk_en <= 1'b1;
+ clk_en_2 <= 1'b1;
clk_en_ssg <= 1'b1;
+ clk_en_666 <= 1'b1;
+ clk_en_55 <= 1'b1;
`else
- clk_en <= cen & cen_int;
- clk_en_ssg <= use_ssg ? (cen & cen_ssg_int) : 1'b0;
+ clk_en <= cen & cen_int;
+ clk_en_2 <= cen && (div2==2'b00);
+ clk_en_ssg <= use_ssg ? (cen & cen_ssg_int) : 1'b0;
+ clk_en_666 <= cen & cen_adpcm_int;
+ clk_en_111 <= cen & cen_adpcm_int & cen_adpcm3_int;
+ clk_en_55 <= cen & cen_adpcm_int & cen_adpcm3_int & cen_55_int;
`endif
end
+// Div/2
+always @(posedge clk)
+ if( cen ) begin
+ div2 <= div2==2'b10 ? 2'b00 : (div2+2'b01);
+ end
+
// OPN
always @(posedge clk)
if( cen ) begin
if( opn_cnt == opn_pres ) begin
- opn_cnt <= 4'd0;
+ opn_cnt <= 4'd0;
end
else opn_cnt <= opn_cnt + 4'd1;
end
@@ -79,4 +127,15 @@ always @(posedge clk)
else ssg_cnt <= ssg_cnt + 3'd1;
end
+// ADPCM-A
+always @(posedge clk)
+ if( cen ) begin
+ adpcm_cnt666 <= adpcm_cnt666==5'd11 ? 5'd0 : adpcm_cnt666 + 5'd1;
+ if( adpcm_cnt666==5'd0 ) begin
+ adpcm_cnt111 <= adpcm_cnt111==3'd5 ? 3'd0 : adpcm_cnt111+3'd1;
+ if( adpcm_cnt111==3'd0)
+ adpcm_cnt55 <= adpcm_cnt55==3'd1 ? 3'd0: adpcm_cnt55+3'd1;
+ end
+ end
+
endmodule // jt12_div
diff --git a/rtl/sound/jt12/jt12_dout.v b/rtl/sound/jt12/jt12_dout.v
new file mode 100644
index 0000000..4666b57
--- /dev/null
+++ b/rtl/sound/jt12/jt12_dout.v
@@ -0,0 +1,47 @@
+/* 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 .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 21-03-2019
+*/
+
+module jt12_dout(
+ // input rst_n,
+ input clk, // CPU clock
+ input flag_A,
+ input flag_B,
+ input busy,
+ input [5:0] adpcma_flags,
+ input adpcmb_flag,
+ input [7:0] psg_dout,
+ input [1:0] addr,
+ output reg [7:0] dout
+);
+
+parameter use_ssg=0, use_adpcm=0;
+
+always @(posedge clk) begin
+ casez( addr )
+ 2'b00: dout <= {busy, 5'd0, flag_B, flag_A }; // YM2203
+ 2'b01: dout <= (use_ssg ==1) ? psg_dout : {busy, 5'd0, flag_B, flag_A };
+ 2'b1?: dout <= (use_adpcm==1) ?
+ { adpcmb_flag, 1'b0, adpcma_flags } :
+ { busy, 5'd0, flag_B, flag_A };
+ endcase
+end
+
+endmodule // jt12_dout
\ No newline at end of file
diff --git a/rtl/sound/jt12/jt12_eg.v b/rtl/sound/jt12/jt12_eg.v
index 4a5dbc9..fbf1064 100644
--- a/rtl/sound/jt12/jt12_eg.v
+++ b/rtl/sound/jt12/jt12_eg.v
@@ -22,7 +22,7 @@
module jt12_eg (
input rst,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input zero,
input eg_stop,
// envelope configuration
diff --git a/rtl/sound/jt12/jt12_eg_cnt.v b/rtl/sound/jt12/jt12_eg_cnt.v
index b83292e..df006d6 100644
--- a/rtl/sound/jt12/jt12_eg_cnt.v
+++ b/rtl/sound/jt12/jt12_eg_cnt.v
@@ -22,14 +22,14 @@
module jt12_eg_cnt(
input rst,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input zero,
output reg [14:0] eg_cnt
);
reg [1:0] eg_cnt_base;
-always @(posedge clk) begin : envelope_counter
+always @(posedge clk, posedge rst) begin : envelope_counter
if( rst ) begin
eg_cnt_base <= 2'd0;
eg_cnt <=15'd0;
diff --git a/rtl/sound/jt12/jt12_eg_ctrl.v b/rtl/sound/jt12/jt12_eg_ctrl.v
index 3b4816b..ddd8698 100644
--- a/rtl/sound/jt12/jt12_eg_ctrl.v
+++ b/rtl/sound/jt12/jt12_eg_ctrl.v
@@ -24,7 +24,7 @@ module jt12_eg_ctrl(
input keyoff_now,
input [2:0] state_in,
input [9:0] eg,
- // envelope configuration
+ // envelope configuration
input [4:0] arate, // attack rate
input [4:0] rate1, // decay rate
input [4:0] rate2, // sustain rate
@@ -42,16 +42,16 @@ module jt12_eg_ctrl(
output reg pg_rst
);
-localparam ATTACK = 3'b001,
- DECAY = 3'b010,
+localparam ATTACK = 3'b001,
+ DECAY = 3'b010,
HOLD = 3'b100,
- RELEASE= 3'b000; // default state is release
+ RELEASE= 3'b000; // default state is release
// wire is_decaying = state_in[1] | state_in[2];
reg [4:0] sustain;
-always @(*)
+always @(*)
if( sl == 4'd15 )
sustain = 5'h1f; // 93dB
else
@@ -74,14 +74,14 @@ always @(*) begin
pg_rst = keyon_now | ssg_pg_rst;
end
-always @(*)
+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}:
+ {2'b00, ATTACK}:
if( eg==10'd0 ) begin
base_rate = rate1;
state_next = DECAY;
@@ -99,7 +99,7 @@ always @(*)
ssg_inv_out = ssg_en & (ssg_alt ^ ssg_inv_in);
end
else begin
- base_rate = eg[9:5] >= sustain ? rate2 : rate1;
+ base_rate = eg[9:5] >= sustain ? rate2 : rate1; // equal comparison according to Nuke
state_next = DECAY;
ssg_inv_out = ssg_inv_in;
end
diff --git a/rtl/sound/jt12/jt12_exprom.v b/rtl/sound/jt12/jt12_exprom.v
index 1bb1891..beca296 100644
--- a/rtl/sound/jt12/jt12_exprom.v
+++ b/rtl/sound/jt12/jt12_exprom.v
@@ -1,4 +1,3 @@
-`timescale 1ns / 1ps
/* This file is part of JT12.
@@ -31,7 +30,7 @@ module jt12_exprom
(
input [7:0] addr,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
output reg [9:0] exp
);
diff --git a/rtl/sound/jt12/jt12_kon.v b/rtl/sound/jt12/jt12_kon.v
index 42cfd00..db4b82c 100644
--- a/rtl/sound/jt12/jt12_kon.v
+++ b/rtl/sound/jt12/jt12_kon.v
@@ -1,4 +1,3 @@
-`timescale 1ns / 1ps
/* This file is part of JT12.
@@ -26,7 +25,7 @@
module jt12_kon(
input rst,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input [3:0] keyon_op,
input [2:0] keyon_ch,
input [1:0] next_op,
@@ -41,29 +40,14 @@ module jt12_kon(
parameter num_ch=6;
-reg din;
wire csr_out;
-reg [3:0] next_op_hot;
-reg [3:0] next_op6_hot;
-
-
-always @(*) begin
- case( next_op )
- 2'd0: next_op_hot = 4'b0001; // S1
- 2'd1: next_op_hot = 4'b0100; // S3
- 2'd2: next_op_hot = 4'b0010; // S2
- 2'd3: next_op_hot = 4'b1000; // S4
- endcase
- din = keyon_ch==next_ch && up_keyon ? |(keyon_op&next_op_hot) : csr_out;
-end
-
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;
@@ -73,40 +57,83 @@ if(num_ch==6) begin
end
end
- wire middle;
- reg mid_din;
-
- always @(posedge clk) if( clk_en )
+ 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
+ reg up_keyon_reg;
+ reg [3:0] tkeyon_op;
+ reg [2:0] tkeyon_ch;
+ wire key_upnow;
- jt12_sh_rst #(.width(1),.stages(12),.rstval(1'b0)) u_konch0(
+ assign key_upnow = up_keyon_reg && (tkeyon_ch==next_ch) && (next_op == 2'd3);
+
+ always @(posedge clk) if( clk_en ) begin
+ if (rst)
+ up_keyon_reg <= 1'b0;
+ if (up_keyon) begin
+ up_keyon_reg <= 1'b1;
+ tkeyon_op <= keyon_op;
+ tkeyon_ch <= keyon_ch; end
+ else if (key_upnow)
+ up_keyon_reg <= 1'b0;
+ end
+
+
+ wire middle1;
+ wire middle2;
+ wire middle3;
+ wire din = key_upnow ? tkeyon_op[3] : csr_out;
+ wire mid_din2 = key_upnow ? tkeyon_op[1] : middle1;
+ wire mid_din3 = key_upnow ? tkeyon_op[2] : middle2;
+ wire mid_din4 = key_upnow ? tkeyon_op[0] : middle3;
+
+ jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch0(
.clk ( clk ),
.clk_en ( clk_en ),
.rst ( rst ),
.din ( din ),
- .drop ( middle )
+ .drop ( middle1 )
);
- jt12_sh_rst #(.width(1),.stages(12),.rstval(1'b0)) u_konch1(
+ jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch1(
.clk ( clk ),
.clk_en ( clk_en ),
.rst ( rst ),
- .din ( mid_din ),
+ .din ( mid_din2 ),
+ .drop ( middle2 )
+ );
+
+ jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch2(
+ .clk ( clk ),
+ .clk_en ( clk_en ),
+ .rst ( rst ),
+ .din ( mid_din3 ),
+ .drop ( middle3 )
+ );
+
+ jt12_sh_rst #(.width(1),.stages(6),.rstval(1'b0)) u_konch3(
+ .clk ( clk ),
+ .clk_en ( clk_en ),
+ .rst ( rst ),
+ .din ( mid_din4 ),
.drop ( csr_out )
);
end
else begin // 3 channels
- always @(posedge clk) if( clk_en )
+ reg din;
+ reg [3:0] next_op_hot;
+
+ always @(*) begin
+ case( next_op )
+ 2'd0: next_op_hot = 4'b0001; // S1
+ 2'd1: next_op_hot = 4'b0100; // S3
+ 2'd2: next_op_hot = 4'b0010; // S2
+ 2'd3: next_op_hot = 4'b1000; // S4
+ endcase
+ din = keyon_ch[1:0]==next_ch[1:0] && up_keyon ? |(keyon_op&next_op_hot) : csr_out;
+ end
+
+ 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(
diff --git a/rtl/sound/jt12/jt12_lfo.v b/rtl/sound/jt12/jt12_lfo.v
index 3f3fa90..7c58efb 100644
--- a/rtl/sound/jt12/jt12_lfo.v
+++ b/rtl/sound/jt12/jt12_lfo.v
@@ -18,7 +18,6 @@
Date: 25-2-2017
*/
-`timescale 1ns / 1ps
/*
diff --git a/rtl/sound/jt12/jt12_limitamp.v b/rtl/sound/jt12/jt12_limitamp.v
deleted file mode 100644
index b990fd0..0000000
--- a/rtl/sound/jt12/jt12_limitamp.v
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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 .
-
- Author: Jose Tejada Gomez. Twitter: @topapate
- Version: 1.0
- Date: March, 10th 2017
- */
-
-/* Limiting amplifier by 3dB * shift */
-
-`timescale 1ns / 1ps
-
-module jt12_limitamp #( parameter width=20, shift=5 ) (
- input signed [width-1:0] left_in,
- input signed [width-1:0] right_in,
- output reg signed [width-1:0] left_out,
- output reg signed [width-1:0] right_out
-);
-
-always @(*) begin
- left_out = ^left_in[width-1:width-1-shift] ?
- { left_in[width-1], {(width-1){~left_in[width-1]}}} :
- left_in <<< shift;
-
- right_out = ^right_in[width-1:width-1-shift] ?
- { right_in[width-1], {(width-1){~right_in[width-1]}}} :
- right_in <<< shift;
-end
-
-endmodule
diff --git a/rtl/sound/jt12/jt12_mmr.v b/rtl/sound/jt12/jt12_mmr.v
index 8839001..d089fd8 100644
--- a/rtl/sound/jt12/jt12_mmr.v
+++ b/rtl/sound/jt12/jt12_mmr.v
@@ -18,19 +18,24 @@
Date: 14-2-2017
*/
-`timescale 1ns / 1ps
module jt12_mmr(
input rst,
input clk,
- input cen,
+ input cen /* synthesis direct_enable */,
output clk_en,
+ output clk_en_2,
output clk_en_ssg,
+ output clk_en_666,
+ output clk_en_111,
+ output clk_en_55,
input [7:0] din,
input write,
input [1:0] addr,
output reg busy,
output ch6op,
+ output [2:0] cur_ch,
+ output [1:0] cur_op,
// LFO
output reg [2:0] lfo_freq,
output reg lfo_en,
@@ -46,10 +51,33 @@ module jt12_mmr(
output reg fast_timers,
input flag_A,
input overflow_A,
+ output reg [1:0] div_setting,
// PCM
output reg [8:0] pcm,
output reg pcm_en,
output reg pcm_wr, // high for one clock cycle when PCM is written
+ // ADPCM-A
+ output reg [ 7:0] aon_a, // ON
+ output reg [ 5:0] atl_a, // TL
+ output reg [15:0] addr_a, // address latch
+ output reg [ 7:0] lracl, // L/R ADPCM Channel Level
+ output reg up_start, // write enable start address latch
+ output reg up_end, // write enable end address latch
+ output reg [ 2:0] up_addr, // write enable end address latch
+ output reg [ 2:0] up_lracl,
+ output reg up_aon, // There was a write AON register
+ // ADPCM-B
+ output reg acmd_on_b, // Control - Process start, Key On
+ output reg acmd_rep_b, // Control - Repeat
+ output reg acmd_rst_b, // Control - Reset
+ output reg acmd_up_b, // Control - New cmd received
+ output reg [ 1:0] alr_b, // Left / Right
+ output reg [15:0] astart_b, // Start address
+ output reg [15:0] aend_b, // End address
+ output reg [15:0] adeltan_b, // Delta-N
+ output reg [ 7:0] aeg_b, // Envelope Generator Control
+ output reg [ 6:0] flag_ctl,
+ output reg [ 6:0] flag_mask,
// Operator
output xuse_prevprev1,
output xuse_internal,
@@ -85,7 +113,6 @@ module jt12_mmr(
output keyon_I,
-// output [ 1:0] cur_op,
// Operator
output zero,
output s1_enters,
@@ -96,33 +123,27 @@ module jt12_mmr(
// PSG interace
output [3:0] psg_addr,
output [7:0] psg_data,
- output reg psg_wr_n
+ output reg psg_wr_n,
+ input [7:0] debug_bus
);
-parameter use_ssg=0, num_ch=6, use_pcm=1;
+parameter use_ssg=0, num_ch=6, use_pcm=1, use_adpcm=0, mask_div=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 )
+jt12_div #(.use_ssg(use_ssg)) u_div (
+ .rst ( rst ),
+ .clk ( clk ),
+ .cen ( cen ),
+ .div_setting ( div_setting ),
+ .clk_en ( clk_en ),
+ .clk_en_2 ( clk_en_2 ),
+ .clk_en_ssg ( clk_en_ssg ),
+ .clk_en_666 ( clk_en_666 ),
+ .clk_en_111 ( clk_en_111 ),
+ .clk_en_55 ( clk_en_55 )
);
reg [7:0] selected_register;
-//reg sch; // 0 => CH1~CH3 only available. 1=>CH4~CH6
/*
reg irq_zero_en, irq_brdy_en, irq_eos_en,
irq_tb_en, irq_ta_en;
@@ -131,9 +152,7 @@ reg [6:0] up_opreg; // hot-one encoding. tells which operator register gets upda
reg [2:0] up_chreg; // hot-one encoding. tells which channel register gets updated next
reg up_keyon;
-wire busy_reg;
-
-parameter REG_TESTYM = 8'h21,
+localparam REG_TESTYM = 8'h21,
REG_LFO = 8'h22,
REG_CLKA1 = 8'h24,
REG_CLKA2 = 8'h25,
@@ -146,8 +165,11 @@ parameter REG_TESTYM = 8'h21,
REG_DACTEST = 8'h2C,
REG_CLK_N6 = 8'h2D,
REG_CLK_N3 = 8'h2E,
- REG_CLK_N2 = 8'h2F;
-
+ REG_CLK_N2 = 8'h2F,
+ // ADPCM (YM2610)
+ REG_ADPCMA_ON = 8'h00,
+ REG_ADPCMA_TL = 8'h01,
+ REG_ADPCMA_TEST = 8'h02;
reg csm, effect;
@@ -159,16 +181,12 @@ reg [ 5:0] latch_fnum;
reg [2:0] up_ch;
reg [1:0] up_op;
-reg old_write;
-reg [7:0] din_copy;
-
-always @(posedge clk)
- old_write <= write;
+reg [7:0] op_din, ch_din;
generate
if( use_ssg ) begin
assign psg_addr = selected_register[3:0];
- assign psg_data = din_copy;
+ assign psg_data = ch_din;
end else begin
assign psg_addr = 4'd0;
assign psg_data = 8'd0;
@@ -177,76 +195,131 @@ endgenerate
reg part;
+`ifdef SIMULATION
+always @(posedge clk) if( write && rst ) begin
+ $display("WARNING [JT12]: detected write request while in reset.\nThis is likely a glue-logic error in the CPU-FM module.");
+ $finish;
+end
+`endif
+
+wire [2:0] ch_sel = {part, selected_register[1:0]};
+
// this runs at clk speed, no clock gating here
+// if I try to make this an async rst it fails to map it
+// as flip flops but uses latches instead. So I keep it as sync. reset
always @(posedge clk) begin : memory_mapped_registers
if( rst ) begin
- selected_register <= 8'h0;
- div_setting <= 2'b11;
- up_ch <= 3'd0;
- up_op <= 2'd0;
- up_keyon <= 1'd0;
- up_opreg <= 7'd0;
- up_chreg <= 3'd0;
+ selected_register <= 0;
+ div_setting <= 2'b10; // FM=1/6, SSG=1/4
+ up_ch <= 0;
+ up_op <= 0;
+ up_keyon <= 0;
+ up_opreg <= 0;
+ up_chreg <= 0;
// IRQ Mask
/*{ irq_zero_en, irq_brdy_en, irq_eos_en,
irq_tb_en, irq_ta_en } = 5'h1f; */
// timers
- { value_A, value_B } <= 18'd0;
+ { value_A, value_B } <= 0;
{ clr_flag_B, clr_flag_A,
- enable_irq_B, enable_irq_A, load_B, load_A } <= 6'd0;
- fast_timers <= 1'b0;
+ enable_irq_B, enable_irq_A, load_B, load_A } <= 0;
+ fast_timers <= 0;
// LFO
- lfo_freq <= 3'd0;
- lfo_en <= 1'b0;
- csm <= 1'b0;
- effect <= 1'b0;
+ lfo_freq <= 0;
+ lfo_en <= 0;
+ csm <= 0;
+ effect <= 0;
// PCM
- pcm <= 9'h0;
- pcm_en <= 1'b0;
- pcm_wr <= 1'b0;
- // sch <= 1'b0;
+ pcm <= 0;
+ pcm_en <= 0;
+ pcm_wr <= 0;
+ // ADPCM-A
+ aon_a <= 0;
+ atl_a <= 0;
+ up_start <= 0;
+ up_end <= 0;
+ up_addr <= 7;
+ up_lracl <= 7;
+ up_aon <= 0;
+ lracl <= 0;
+ addr_a <= 0;
+ // ADPCM-B
+ acmd_on_b <= 0;
+ acmd_rep_b <= 0;
+ acmd_rst_b <= 0;
+ alr_b <= 0;
+ flag_ctl <= 0;
+ astart_b <= 0;
+ aend_b <= 0;
+ adeltan_b <= 0;
+ flag_mask <= 0;
+ aeg_b <= 8'hff;
// Original test features
- eg_stop <= 1'b0;
- pg_stop <= 1'b0;
- psg_wr_n <= 1'b1;
+ eg_stop <= 0;
+ pg_stop <= 0;
+ psg_wr_n <= 1;
+ //
+ { block_ch3op1, fnum_ch3op1 } <= {3'd0, 11'd0 };
+ { block_ch3op3, fnum_ch3op3 } <= {3'd0, 11'd0 };
+ { block_ch3op2, fnum_ch3op2 } <= {3'd0, 11'd0 };
+ latch_fnum <= 0;
+ op_din <= 0;
+ part <= 0;
end else begin
+ up_chreg <= 0;
// WRITE IN REGISTERS
if( write ) begin
if( !addr[0] ) begin
selected_register <= din;
- part <= addr[1];
+ part <= addr[1];
+ if (!mask_div)
+ case(din)
+ // clock divider: should work only for ym2203
+ // and ym2608.
+ // clock divider works just by selecting the register
+ REG_CLK_N6: div_setting[1] <= 1'b1; // 2D
+ REG_CLK_N3: div_setting[0] <= 1'b1; // 2E
+ REG_CLK_N2: div_setting <= 2'b0; // 2F
+ default:;
+ endcase
end else begin
// Global registers
- din_copy <= din;
- up_keyon <= selected_register == REG_KON;
- up_ch <= {part, selected_register[1:0]};
- up_op <= selected_register[3:2]; // 0=S1,1=S3,2=S2,3=S4
+ ch_din <= din;
+ if( selected_register == REG_KON && !part ) begin
+ up_keyon <= 1;
+ op_din <= din;
+ end else begin
+ up_keyon <= 0;
+ end
+ // General control (<0x20 registers and A0==0)
+ if(!part) begin
+ casez( selected_register)
+ //REG_TEST: lfo_rst <= 1'b1; // regardless of din
+ 8'h0?: psg_wr_n <= 1'b0;
+ REG_TESTYM: begin
+ eg_stop <= din[5];
+ pg_stop <= din[3];
+ fast_timers <= din[2];
+ end
+ REG_CLKA1: value_A[9:2]<= din;
+ REG_CLKA2: value_A[1:0]<= din[1:0];
+ REG_CLKB: value_B <= din;
+ REG_TIMER: begin
+ effect <= |din[7:6];
+ csm <= din[7:6] == 2'b10;
+ { clr_flag_B, clr_flag_A,
+ enable_irq_B, enable_irq_A,
+ load_B, load_A } <= din[5:0];
+ end
+ `ifndef NOLFO
+ REG_LFO: { lfo_en, lfo_freq } <= din[3:0];
+ `endif
+ default:;
+ endcase
+ end
+
+ // CH3 special registers
casez( selected_register)
- //REG_TEST: lfo_rst <= 1'b1; // regardless of din
- 8'h0?: psg_wr_n <= 1'b0;
- REG_TESTYM: begin
- eg_stop <= din[5];
- pg_stop <= din[3];
- fast_timers <= din[2];
- end
- REG_CLKA1: value_A[9:2]<= din;
- REG_CLKA2: value_A[1:0]<= din[1:0];
- REG_CLKB: value_B <= din;
- REG_TIMER: begin
- effect <= |din[7:6];
- csm <= din[7:6] == 2'b10;
- { clr_flag_B, clr_flag_A,
- enable_irq_B, enable_irq_A,
- load_B, load_A } <= din[5:0];
- end
- `ifndef NOLFO
- REG_LFO: { lfo_en, lfo_freq } <= din[3:0];
- `endif
- // clock divider
- REG_CLK_N6: div_setting[1] <= 1'b1;
- REG_CLK_N3: div_setting[0] <= 1'b1;
- REG_CLK_N2: div_setting <= 2'b0;
- // 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 };
@@ -255,7 +328,9 @@ always @(posedge clk) begin : memory_mapped_registers
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
+
+ // YM2612 PCM support
+ if( use_pcm==1 ) begin
casez( selected_register)
REG_DACTEST: pcm[0] <= din[3];
REG_PCM:
@@ -265,9 +340,60 @@ always @(posedge clk) begin : memory_mapped_registers
endcase
pcm_wr <= selected_register==REG_PCM;
end
+ if( use_adpcm==1 ) begin
+ // YM2610 ADPCM-A support, A1=1, regs 0-2D
+ if(part && selected_register[7:6]==2'b0) begin
+ casez( selected_register[5:0] )
+ 6'h0: begin
+ aon_a <= din;
+ up_aon <= 1'b1;
+ end
+ 6'h1: atl_a <= din[5:0];
+ // LRACL
+ 6'h8, 6'h9, 6'hA, 6'hB, 6'hC, 6'hD: begin
+ lracl <= din;
+ up_lracl <= selected_register[2:0];
+ end
+ 6'b01_????, 6'b10_????: begin
+ if( !selected_register[3] ) addr_a[ 7:0] <= din;
+ if( selected_register[3] ) addr_a[15:8] <= din;
+ case( selected_register[5:4] )
+ 2'b01, 2'b10: begin
+ {up_end, up_start } <= selected_register[5:4];
+ up_addr <= selected_register[2:0];
+ end
+ default: begin
+ up_start <= 1'b0;
+ up_end <= 1'b0;
+ end
+ endcase
+ end
+ default:;
+ endcase
+ end
+ if( !part && selected_register[7:4]==4'h1 ) begin
+ // YM2610 ADPCM-B support, A1=0, regs 1x
+ case(selected_register[3:0])
+ 4'd0: {acmd_up_b, acmd_on_b, acmd_rep_b,acmd_rst_b} <= {1'd1,din[7],din[4],din[0]};
+ 4'd1: alr_b <= din[7:6];
+ 4'd2: astart_b [ 7:0] <= din;
+ 4'd3: astart_b [15:8] <= din;
+ 4'd4: aend_b [ 7:0] <= din;
+ 4'd5: aend_b [15:8] <= din;
+ 4'h9: adeltan_b[ 7:0] <= din;
+ 4'ha: adeltan_b[15:8] <= din;
+ 4'hb: aeg_b <= din;
+ 4'hc: begin
+ flag_mask <= ~{din[7],din[5:0]};
+ flag_ctl <= {din[7],din[5:0]}; // this lasts a single clock cycle
+ end
+ default:;
+ endcase
+ end
+ end
if( selected_register[1:0]==2'b11 )
{ up_chreg, up_opreg } <= { 3'h0, 7'h0 };
- else
+ else begin
casez( selected_register )
// channel registers
8'hA0, 8'hA1, 8'hA2: { up_chreg, up_opreg } <= { 3'h1, 7'd0 }; // up_fnumlo
@@ -284,45 +410,59 @@ always @(posedge clk) begin : memory_mapped_registers
8'h9?: { up_chreg, up_opreg } <= { 3'h0, 7'h40 }; // up_ssgeg
default: { up_chreg, up_opreg } <= { 3'h0, 7'h0 };
endcase // selected_register
+ if( selected_register[7:4]>=3 && selected_register[7:4]<=9 ) begin
+ op_din <= din;
+ up_ch <= {part, selected_register[1:0]};
+ up_op <= selected_register[3:2]; // 0=S1,1=S3,2=S2,3=S4
+ end
+ end
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;
+ pcm_wr <= 1'b0;
+ flag_ctl <= 'd0;
+ up_aon <= 1'b0;
+ acmd_up_b <= 1'b0;
end
end
end
-reg [4:0] busy_cnt; // busy lasts for 32 synth clock cycles, like in real chip
+reg [4:0] busy_cnt; // busy lasts for 32 synthesizer clock cycles
+wire [5:0] nx_busy = {1'd0,busy_cnt}+{5'd0,busy};
-always @(posedge clk)
+always @(posedge clk, posedge rst) begin
if( rst ) begin
- busy <= 1'b0;
- busy_cnt <= 5'd0;
- end
- else begin
- if (!old_write && write && addr[0] ) begin // only set for data writes
- busy <= 1'b1;
- busy_cnt <= 5'd0;
- end
- else if(clk_en) begin
- if( busy_cnt == 5'd31 ) busy <= 1'b0;
- busy_cnt <= busy_cnt+5'd1;
+ busy <= 0;
+ busy_cnt <= 0;
+ end else begin
+ if( write&addr[0] ) begin
+ busy <= 1;
+ busy_cnt <= 0;
+ end else if(clk_en) begin
+ busy <= ~nx_busy[5] & busy;
+ busy_cnt <= nx_busy[4:0];
end
end
+end
jt12_reg #(.num_ch(num_ch)) u_reg(
.rst ( rst ),
.clk ( clk ), // P1
.clk_en ( clk_en ),
- .din ( din_copy ),
- .up_keyon ( up_keyon ),
+ // channel udpates
+ .ch_sel ( ch_sel ),
+ .ch_din ( ch_din ),
.up_fnumlo ( up_chreg[0] ),
.up_alg ( up_chreg[1] ),
.up_pms ( up_chreg[2] ),
+
+ // operator updates
+ .din ( op_din ),
+ .up_keyon ( up_keyon ),
.up_dt1 ( up_opreg[0] ),
.up_tl ( up_opreg[1] ),
.up_ks_ar ( up_opreg[2] ),
@@ -339,6 +479,8 @@ jt12_reg #(.num_ch(num_ch)) u_reg(
.overflow_A ( overflow_A),
.ch6op ( ch6op ),
+ .cur_ch ( cur_ch ),
+ .cur_op ( cur_op ),
// CH3 Effect-mode operation
.effect ( effect ), // allows independent freq. for CH 3
.fnum_ch3op2( fnum_ch3op2 ),
diff --git a/rtl/sound/jt12/jt12_mmr_sim.vh b/rtl/sound/jt12/jt12_mmr_sim.vh
deleted file mode 100644
index 96d60d8..0000000
--- a/rtl/sound/jt12/jt12_mmr_sim.vh
+++ /dev/null
@@ -1,854 +0,0 @@
-`ifdef SIMULATION
-/* verilator lint_off PINMISSING */
-
-reg [4:0] sep24_cnt;
-reg mmr_dump;
-
-always @(posedge clk ) if(clk_en)
- sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
-
-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(1) ) fnum_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( fnum_I ),
- .mask ( 24'd0 ),
- .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 [2:0] block_ch0s1, block_ch1s1, block_ch2s1, block_ch3s1,
- block_ch4s1, block_ch5s1, block_ch0s2, block_ch1s2,
- block_ch2s2, block_ch3s2, block_ch4s2, block_ch5s2,
- block_ch0s3, block_ch1s3, block_ch2s3, block_ch3s3,
- block_ch4s3, block_ch5s3, block_ch0s4, block_ch1s4,
- block_ch2s4, block_ch3s4, block_ch4s4, block_ch5s4;
-
-sep24 #( .width(3), .pos0(1) ) block_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( block_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (block_ch0s1),
- .ch1s1 (block_ch1s1),
- .ch2s1 (block_ch2s1),
- .ch3s1 (block_ch3s1),
- .ch4s1 (block_ch4s1),
- .ch5s1 (block_ch5s1),
-
- .ch0s2 (block_ch0s2),
- .ch1s2 (block_ch1s2),
- .ch2s2 (block_ch2s2),
- .ch3s2 (block_ch3s2),
- .ch4s2 (block_ch4s2),
- .ch5s2 (block_ch5s2),
-
- .ch0s3 (block_ch0s3),
- .ch1s3 (block_ch1s3),
- .ch2s3 (block_ch2s3),
- .ch3s3 (block_ch3s3),
- .ch4s3 (block_ch4s3),
- .ch5s3 (block_ch5s3),
-
- .ch0s4 (block_ch0s4),
- .ch1s4 (block_ch1s4),
- .ch2s4 (block_ch2s4),
- .ch3s4 (block_ch3s4),
- .ch4s4 (block_ch4s4),
- .ch5s4 (block_ch5s4)
-);
-
-wire [1:0] rl_ch0s1, rl_ch1s1, rl_ch2s1, rl_ch3s1,
- rl_ch4s1, rl_ch5s1, rl_ch0s2, rl_ch1s2,
- rl_ch2s2, rl_ch3s2, rl_ch4s2, rl_ch5s2,
- rl_ch0s3, rl_ch1s3, rl_ch2s3, rl_ch3s3,
- rl_ch4s3, rl_ch5s3, rl_ch0s4, rl_ch1s4,
- rl_ch2s4, rl_ch3s4, rl_ch4s4, rl_ch5s4;
-
-sep24 #( .width(2), .pos0(1) ) rl_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( rl ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (rl_ch0s1),
- .ch1s1 (rl_ch1s1),
- .ch2s1 (rl_ch2s1),
- .ch3s1 (rl_ch3s1),
- .ch4s1 (rl_ch4s1),
- .ch5s1 (rl_ch5s1),
-
- .ch0s2 (rl_ch0s2),
- .ch1s2 (rl_ch1s2),
- .ch2s2 (rl_ch2s2),
- .ch3s2 (rl_ch3s2),
- .ch4s2 (rl_ch4s2),
- .ch5s2 (rl_ch5s2),
-
- .ch0s3 (rl_ch0s3),
- .ch1s3 (rl_ch1s3),
- .ch2s3 (rl_ch2s3),
- .ch3s3 (rl_ch3s3),
- .ch4s3 (rl_ch4s3),
- .ch5s3 (rl_ch5s3),
-
- .ch0s4 (rl_ch0s4),
- .ch1s4 (rl_ch1s4),
- .ch2s4 (rl_ch2s4),
- .ch3s4 (rl_ch3s4),
- .ch4s4 (rl_ch4s4),
- .ch5s4 (rl_ch5s4)
-);
-
-wire [2:0] fb_ch0s1, fb_ch1s1, fb_ch2s1, fb_ch3s1,
- fb_ch4s1, fb_ch5s1, fb_ch0s2, fb_ch1s2,
- fb_ch2s2, fb_ch3s2, fb_ch4s2, fb_ch5s2,
- fb_ch0s3, fb_ch1s3, fb_ch2s3, fb_ch3s3,
- fb_ch4s3, fb_ch5s3, fb_ch0s4, fb_ch1s4,
- fb_ch2s4, fb_ch3s4, fb_ch4s4, fb_ch5s4;
-
-sep24 #( .width(3), .pos0(0) ) fb_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( fb_II ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (fb_ch0s1),
- .ch1s1 (fb_ch1s1),
- .ch2s1 (fb_ch2s1),
- .ch3s1 (fb_ch3s1),
- .ch4s1 (fb_ch4s1),
- .ch5s1 (fb_ch5s1),
-
- .ch0s2 (fb_ch0s2),
- .ch1s2 (fb_ch1s2),
- .ch2s2 (fb_ch2s2),
- .ch3s2 (fb_ch3s2),
- .ch4s2 (fb_ch4s2),
- .ch5s2 (fb_ch5s2),
-
- .ch0s3 (fb_ch0s3),
- .ch1s3 (fb_ch1s3),
- .ch2s3 (fb_ch2s3),
- .ch3s3 (fb_ch3s3),
- .ch4s3 (fb_ch4s3),
- .ch5s3 (fb_ch5s3),
-
- .ch0s4 (fb_ch0s4),
- .ch1s4 (fb_ch1s4),
- .ch2s4 (fb_ch2s4),
- .ch3s4 (fb_ch3s4),
- .ch4s4 (fb_ch4s4),
- .ch5s4 (fb_ch5s4)
-);
-
-wire [2:0] alg_ch0s1, alg_ch1s1, alg_ch2s1, alg_ch3s1,
- alg_ch4s1, alg_ch5s1, alg_ch0s2, alg_ch1s2,
- alg_ch2s2, alg_ch3s2, alg_ch4s2, alg_ch5s2,
- alg_ch0s3, alg_ch1s3, alg_ch2s3, alg_ch3s3,
- alg_ch4s3, alg_ch5s3, alg_ch0s4, alg_ch1s4,
- alg_ch2s4, alg_ch3s4, alg_ch4s4, alg_ch5s4;
-
-sep24 #( .width(3), .pos0(1) ) alg_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( alg ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (alg_ch0s1),
- .ch1s1 (alg_ch1s1),
- .ch2s1 (alg_ch2s1),
- .ch3s1 (alg_ch3s1),
- .ch4s1 (alg_ch4s1),
- .ch5s1 (alg_ch5s1),
-
- .ch0s2 (alg_ch0s2),
- .ch1s2 (alg_ch1s2),
- .ch2s2 (alg_ch2s2),
- .ch3s2 (alg_ch3s2),
- .ch4s2 (alg_ch4s2),
- .ch5s2 (alg_ch5s2),
-
- .ch0s3 (alg_ch0s3),
- .ch1s3 (alg_ch1s3),
- .ch2s3 (alg_ch2s3),
- .ch3s3 (alg_ch3s3),
- .ch4s3 (alg_ch4s3),
- .ch5s3 (alg_ch5s3),
-
- .ch0s4 (alg_ch0s4),
- .ch1s4 (alg_ch1s4),
- .ch2s4 (alg_ch2s4),
- .ch3s4 (alg_ch3s4),
- .ch4s4 (alg_ch4s4),
- .ch5s4 (alg_ch5s4)
-);
-
-wire [2:0] dt1_ch0s1, dt1_ch1s1, dt1_ch2s1, dt1_ch3s1,
- dt1_ch4s1, dt1_ch5s1, dt1_ch0s2, dt1_ch1s2,
- dt1_ch2s2, dt1_ch3s2, dt1_ch4s2, dt1_ch5s2,
- dt1_ch0s3, dt1_ch1s3, dt1_ch2s3, dt1_ch3s3,
- dt1_ch4s3, dt1_ch5s3, dt1_ch0s4, dt1_ch1s4,
- dt1_ch2s4, dt1_ch3s4, dt1_ch4s4, dt1_ch5s4;
-
-sep24 #( .width(3), .pos0(0) ) dt1_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( dt1_II ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (dt1_ch0s1),
- .ch1s1 (dt1_ch1s1),
- .ch2s1 (dt1_ch2s1),
- .ch3s1 (dt1_ch3s1),
- .ch4s1 (dt1_ch4s1),
- .ch5s1 (dt1_ch5s1),
-
- .ch0s2 (dt1_ch0s2),
- .ch1s2 (dt1_ch1s2),
- .ch2s2 (dt1_ch2s2),
- .ch3s2 (dt1_ch3s2),
- .ch4s2 (dt1_ch4s2),
- .ch5s2 (dt1_ch5s2),
-
- .ch0s3 (dt1_ch0s3),
- .ch1s3 (dt1_ch1s3),
- .ch2s3 (dt1_ch2s3),
- .ch3s3 (dt1_ch3s3),
- .ch4s3 (dt1_ch4s3),
- .ch5s3 (dt1_ch5s3),
-
- .ch0s4 (dt1_ch0s4),
- .ch1s4 (dt1_ch1s4),
- .ch2s4 (dt1_ch2s4),
- .ch3s4 (dt1_ch3s4),
- .ch4s4 (dt1_ch4s4),
- .ch5s4 (dt1_ch5s4)
-);
-
-wire [3:0] mul_ch0s1, mul_ch1s1, mul_ch2s1, mul_ch3s1,
- mul_ch4s1, mul_ch5s1, mul_ch0s2, mul_ch1s2,
- mul_ch2s2, mul_ch3s2, mul_ch4s2, mul_ch5s2,
- mul_ch0s3, mul_ch1s3, mul_ch2s3, mul_ch3s3,
- mul_ch4s3, mul_ch5s3, mul_ch0s4, mul_ch1s4,
- mul_ch2s4, mul_ch3s4, mul_ch4s4, mul_ch5s4;
-
-sep24 #( .width(4), .pos0(21) ) mul_sep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( mul_V ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (mul_ch0s1),
- .ch1s1 (mul_ch1s1),
- .ch2s1 (mul_ch2s1),
- .ch3s1 (mul_ch3s1),
- .ch4s1 (mul_ch4s1),
- .ch5s1 (mul_ch5s1),
-
- .ch0s2 (mul_ch0s2),
- .ch1s2 (mul_ch1s2),
- .ch2s2 (mul_ch2s2),
- .ch3s2 (mul_ch3s2),
- .ch4s2 (mul_ch4s2),
- .ch5s2 (mul_ch5s2),
-
- .ch0s3 (mul_ch0s3),
- .ch1s3 (mul_ch1s3),
- .ch2s3 (mul_ch2s3),
- .ch3s3 (mul_ch3s3),
- .ch4s3 (mul_ch4s3),
- .ch5s3 (mul_ch5s3),
-
- .ch0s4 (mul_ch0s4),
- .ch1s4 (mul_ch1s4),
- .ch2s4 (mul_ch2s4),
- .ch3s4 (mul_ch3s4),
- .ch4s4 (mul_ch4s4),
- .ch5s4 (mul_ch5s4)
-);
-
-wire [6:0] tl_ch0s1, tl_ch1s1, tl_ch2s1, tl_ch3s1,
- tl_ch4s1, tl_ch5s1, tl_ch0s2, tl_ch1s2,
- tl_ch2s2, tl_ch3s2, tl_ch4s2, tl_ch5s2,
- tl_ch0s3, tl_ch1s3, tl_ch2s3, tl_ch3s3,
- tl_ch4s3, tl_ch5s3, tl_ch0s4, tl_ch1s4,
- tl_ch2s4, tl_ch3s4, tl_ch4s4, tl_ch5s4;
-
-sep24 #( .width(7), .pos0(22) ) tl_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( tl_IV ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (tl_ch0s1),
- .ch1s1 (tl_ch1s1),
- .ch2s1 (tl_ch2s1),
- .ch3s1 (tl_ch3s1),
- .ch4s1 (tl_ch4s1),
- .ch5s1 (tl_ch5s1),
-
- .ch0s2 (tl_ch0s2),
- .ch1s2 (tl_ch1s2),
- .ch2s2 (tl_ch2s2),
- .ch3s2 (tl_ch3s2),
- .ch4s2 (tl_ch4s2),
- .ch5s2 (tl_ch5s2),
-
- .ch0s3 (tl_ch0s3),
- .ch1s3 (tl_ch1s3),
- .ch2s3 (tl_ch2s3),
- .ch3s3 (tl_ch3s3),
- .ch4s3 (tl_ch4s3),
- .ch5s3 (tl_ch5s3),
-
- .ch0s4 (tl_ch0s4),
- .ch1s4 (tl_ch1s4),
- .ch2s4 (tl_ch2s4),
- .ch3s4 (tl_ch3s4),
- .ch4s4 (tl_ch4s4),
- .ch5s4 (tl_ch5s4)
-);
-
-wire [4:0] ar_ch0s1, ar_ch1s1, ar_ch2s1, ar_ch3s1,
- ar_ch4s1, ar_ch5s1, ar_ch0s2, ar_ch1s2,
- ar_ch2s2, ar_ch3s2, ar_ch4s2, ar_ch5s2,
- ar_ch0s3, ar_ch1s3, ar_ch2s3, ar_ch3s3,
- ar_ch4s3, ar_ch5s3, ar_ch0s4, ar_ch1s4,
- ar_ch2s4, ar_ch3s4, ar_ch4s4, ar_ch5s4;
-
-sep24 #( .width(5), .pos0(1) ) ar_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( ar_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (ar_ch0s1),
- .ch1s1 (ar_ch1s1),
- .ch2s1 (ar_ch2s1),
- .ch3s1 (ar_ch3s1),
- .ch4s1 (ar_ch4s1),
- .ch5s1 (ar_ch5s1),
-
- .ch0s2 (ar_ch0s2),
- .ch1s2 (ar_ch1s2),
- .ch2s2 (ar_ch2s2),
- .ch3s2 (ar_ch3s2),
- .ch4s2 (ar_ch4s2),
- .ch5s2 (ar_ch5s2),
-
- .ch0s3 (ar_ch0s3),
- .ch1s3 (ar_ch1s3),
- .ch2s3 (ar_ch2s3),
- .ch3s3 (ar_ch3s3),
- .ch4s3 (ar_ch4s3),
- .ch5s3 (ar_ch5s3),
-
- .ch0s4 (ar_ch0s4),
- .ch1s4 (ar_ch1s4),
- .ch2s4 (ar_ch2s4),
- .ch3s4 (ar_ch3s4),
- .ch4s4 (ar_ch4s4),
- .ch5s4 (ar_ch5s4)
-);
-
-wire [4:0] d1r_ch0s1, d1r_ch1s1, d1r_ch2s1, d1r_ch3s1,
- d1r_ch4s1, d1r_ch5s1, d1r_ch0s2, d1r_ch1s2,
- d1r_ch2s2, d1r_ch3s2, d1r_ch4s2, d1r_ch5s2,
- d1r_ch0s3, d1r_ch1s3, d1r_ch2s3, d1r_ch3s3,
- d1r_ch4s3, d1r_ch5s3, d1r_ch0s4, d1r_ch1s4,
- d1r_ch2s4, d1r_ch3s4, d1r_ch4s4, d1r_ch5s4;
-
-sep24 #( .width(5), .pos0(1) ) d1r_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( d1r_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (d1r_ch0s1),
- .ch1s1 (d1r_ch1s1),
- .ch2s1 (d1r_ch2s1),
- .ch3s1 (d1r_ch3s1),
- .ch4s1 (d1r_ch4s1),
- .ch5s1 (d1r_ch5s1),
-
- .ch0s2 (d1r_ch0s2),
- .ch1s2 (d1r_ch1s2),
- .ch2s2 (d1r_ch2s2),
- .ch3s2 (d1r_ch3s2),
- .ch4s2 (d1r_ch4s2),
- .ch5s2 (d1r_ch5s2),
-
- .ch0s3 (d1r_ch0s3),
- .ch1s3 (d1r_ch1s3),
- .ch2s3 (d1r_ch2s3),
- .ch3s3 (d1r_ch3s3),
- .ch4s3 (d1r_ch4s3),
- .ch5s3 (d1r_ch5s3),
-
- .ch0s4 (d1r_ch0s4),
- .ch1s4 (d1r_ch1s4),
- .ch2s4 (d1r_ch2s4),
- .ch3s4 (d1r_ch3s4),
- .ch4s4 (d1r_ch4s4),
- .ch5s4 (d1r_ch5s4)
-);
-
-wire [4:0] d2r_ch0s1, d2r_ch1s1, d2r_ch2s1, d2r_ch3s1,
- d2r_ch4s1, d2r_ch5s1, d2r_ch0s2, d2r_ch1s2,
- d2r_ch2s2, d2r_ch3s2, d2r_ch4s2, d2r_ch5s2,
- d2r_ch0s3, d2r_ch1s3, d2r_ch2s3, d2r_ch3s3,
- d2r_ch4s3, d2r_ch5s3, d2r_ch0s4, d2r_ch1s4,
- d2r_ch2s4, d2r_ch3s4, d2r_ch4s4, d2r_ch5s4;
-
-sep24 #( .width(5), .pos0(1) ) d2r_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( d2r_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (d2r_ch0s1),
- .ch1s1 (d2r_ch1s1),
- .ch2s1 (d2r_ch2s1),
- .ch3s1 (d2r_ch3s1),
- .ch4s1 (d2r_ch4s1),
- .ch5s1 (d2r_ch5s1),
-
- .ch0s2 (d2r_ch0s2),
- .ch1s2 (d2r_ch1s2),
- .ch2s2 (d2r_ch2s2),
- .ch3s2 (d2r_ch3s2),
- .ch4s2 (d2r_ch4s2),
- .ch5s2 (d2r_ch5s2),
-
- .ch0s3 (d2r_ch0s3),
- .ch1s3 (d2r_ch1s3),
- .ch2s3 (d2r_ch2s3),
- .ch3s3 (d2r_ch3s3),
- .ch4s3 (d2r_ch4s3),
- .ch5s3 (d2r_ch5s3),
-
- .ch0s4 (d2r_ch0s4),
- .ch1s4 (d2r_ch1s4),
- .ch2s4 (d2r_ch2s4),
- .ch3s4 (d2r_ch3s4),
- .ch4s4 (d2r_ch4s4),
- .ch5s4 (d2r_ch5s4)
-);
-
-wire [3:0] rr_ch0s1, rr_ch1s1, rr_ch2s1, rr_ch3s1,
- rr_ch4s1, rr_ch5s1, rr_ch0s2, rr_ch1s2,
- rr_ch2s2, rr_ch3s2, rr_ch4s2, rr_ch5s2,
- rr_ch0s3, rr_ch1s3, rr_ch2s3, rr_ch3s3,
- rr_ch4s3, rr_ch5s3, rr_ch0s4, rr_ch1s4,
- rr_ch2s4, rr_ch3s4, rr_ch4s4, rr_ch5s4;
-
-sep24 #( .width(4), .pos0(1) ) rr_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( rr_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (rr_ch0s1),
- .ch1s1 (rr_ch1s1),
- .ch2s1 (rr_ch2s1),
- .ch3s1 (rr_ch3s1),
- .ch4s1 (rr_ch4s1),
- .ch5s1 (rr_ch5s1),
-
- .ch0s2 (rr_ch0s2),
- .ch1s2 (rr_ch1s2),
- .ch2s2 (rr_ch2s2),
- .ch3s2 (rr_ch3s2),
- .ch4s2 (rr_ch4s2),
- .ch5s2 (rr_ch5s2),
-
- .ch0s3 (rr_ch0s3),
- .ch1s3 (rr_ch1s3),
- .ch2s3 (rr_ch2s3),
- .ch3s3 (rr_ch3s3),
- .ch4s3 (rr_ch4s3),
- .ch5s3 (rr_ch5s3),
-
- .ch0s4 (rr_ch0s4),
- .ch1s4 (rr_ch1s4),
- .ch2s4 (rr_ch2s4),
- .ch3s4 (rr_ch3s4),
- .ch4s4 (rr_ch4s4),
- .ch5s4 (rr_ch5s4)
-);
-
-wire [3:0] d1l_ch0s1, d1l_ch1s1, d1l_ch2s1, d1l_ch3s1,
- d1l_ch4s1, d1l_ch5s1, d1l_ch0s2, d1l_ch1s2,
- d1l_ch2s2, d1l_ch3s2, d1l_ch4s2, d1l_ch5s2,
- d1l_ch0s3, d1l_ch1s3, d1l_ch2s3, d1l_ch3s3,
- d1l_ch4s3, d1l_ch5s3, d1l_ch0s4, d1l_ch1s4,
- d1l_ch2s4, d1l_ch3s4, d1l_ch4s4, d1l_ch5s4;
-
-sep24 #( .width(4), .pos0(1) ) d1l_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( sl_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (d1l_ch0s1),
- .ch1s1 (d1l_ch1s1),
- .ch2s1 (d1l_ch2s1),
- .ch3s1 (d1l_ch3s1),
- .ch4s1 (d1l_ch4s1),
- .ch5s1 (d1l_ch5s1),
-
- .ch0s2 (d1l_ch0s2),
- .ch1s2 (d1l_ch1s2),
- .ch2s2 (d1l_ch2s2),
- .ch3s2 (d1l_ch3s2),
- .ch4s2 (d1l_ch4s2),
- .ch5s2 (d1l_ch5s2),
-
- .ch0s3 (d1l_ch0s3),
- .ch1s3 (d1l_ch1s3),
- .ch2s3 (d1l_ch2s3),
- .ch3s3 (d1l_ch3s3),
- .ch4s3 (d1l_ch4s3),
- .ch5s3 (d1l_ch5s3),
-
- .ch0s4 (d1l_ch0s4),
- .ch1s4 (d1l_ch1s4),
- .ch2s4 (d1l_ch2s4),
- .ch3s4 (d1l_ch3s4),
- .ch4s4 (d1l_ch4s4),
- .ch5s4 (d1l_ch5s4)
-);
-
-wire [1:0] ks_ch0s1, ks_ch1s1, ks_ch2s1, ks_ch3s1,
- ks_ch4s1, ks_ch5s1, ks_ch0s2, ks_ch1s2,
- ks_ch2s2, ks_ch3s2, ks_ch4s2, ks_ch5s2,
- ks_ch0s3, ks_ch1s3, ks_ch2s3, ks_ch3s3,
- ks_ch4s3, ks_ch5s3, ks_ch0s4, ks_ch1s4,
- ks_ch2s4, ks_ch3s4, ks_ch4s4, ks_ch5s4;
-
-sep24 #( .width(2), .pos0(0) ) ks_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( ks_II ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (ks_ch0s1),
- .ch1s1 (ks_ch1s1),
- .ch2s1 (ks_ch2s1),
- .ch3s1 (ks_ch3s1),
- .ch4s1 (ks_ch4s1),
- .ch5s1 (ks_ch5s1),
-
- .ch0s2 (ks_ch0s2),
- .ch1s2 (ks_ch1s2),
- .ch2s2 (ks_ch2s2),
- .ch3s2 (ks_ch3s2),
- .ch4s2 (ks_ch4s2),
- .ch5s2 (ks_ch5s2),
-
- .ch0s3 (ks_ch0s3),
- .ch1s3 (ks_ch1s3),
- .ch2s3 (ks_ch2s3),
- .ch3s3 (ks_ch3s3),
- .ch4s3 (ks_ch4s3),
- .ch5s3 (ks_ch5s3),
-
- .ch0s4 (ks_ch0s4),
- .ch1s4 (ks_ch1s4),
- .ch2s4 (ks_ch2s4),
- .ch3s4 (ks_ch3s4),
- .ch4s4 (ks_ch4s4),
- .ch5s4 (ks_ch5s4)
-);
-
-wire [3:0] ssg_I = {ssg_en_I, ssg_eg_I};
-
-wire [3:0] ssg_ch0s1, ssg_ch1s1, ssg_ch2s1, ssg_ch3s1,
- ssg_ch4s1, ssg_ch5s1, ssg_ch0s2, ssg_ch1s2,
- ssg_ch2s2, ssg_ch3s2, ssg_ch4s2, ssg_ch5s2,
- ssg_ch0s3, ssg_ch1s3, ssg_ch2s3, ssg_ch3s3,
- ssg_ch4s3, ssg_ch5s3, ssg_ch0s4, ssg_ch1s4,
- ssg_ch2s4, ssg_ch3s4, ssg_ch4s4, ssg_ch5s4;
-
-sep24 #( .width(4), .pos0(1) ) ssg_step
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( ssg_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (ssg_ch0s1),
- .ch1s1 (ssg_ch1s1),
- .ch2s1 (ssg_ch2s1),
- .ch3s1 (ssg_ch3s1),
- .ch4s1 (ssg_ch4s1),
- .ch5s1 (ssg_ch5s1),
-
- .ch0s2 (ssg_ch0s2),
- .ch1s2 (ssg_ch1s2),
- .ch2s2 (ssg_ch2s2),
- .ch3s2 (ssg_ch3s2),
- .ch4s2 (ssg_ch4s2),
- .ch5s2 (ssg_ch5s2),
-
- .ch0s3 (ssg_ch0s3),
- .ch1s3 (ssg_ch1s3),
- .ch2s3 (ssg_ch2s3),
- .ch3s3 (ssg_ch3s3),
- .ch4s3 (ssg_ch4s3),
- .ch5s3 (ssg_ch5s3),
-
- .ch0s4 (ssg_ch0s4),
- .ch1s4 (ssg_ch1s4),
- .ch2s4 (ssg_ch2s4),
- .ch3s4 (ssg_ch3s4),
- .ch4s4 (ssg_ch4s4),
- .ch5s4 (ssg_ch5s4)
-);
-
-wire kon_ch0s1, kon_ch1s1, kon_ch2s1, kon_ch3s1,
- kon_ch4s1, kon_ch5s1, kon_ch0s2, kon_ch1s2,
- kon_ch2s2, kon_ch3s2, kon_ch4s2, kon_ch5s2,
- kon_ch0s3, kon_ch1s3, kon_ch2s3, kon_ch3s3,
- kon_ch4s3, kon_ch5s3, kon_ch0s4, kon_ch1s4,
- kon_ch2s4, kon_ch3s4, kon_ch4s4, kon_ch5s4;
-
-sep24 #( .width(1), .pos0(1) ) konstep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( keyon_I ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (kon_ch0s1),
- .ch1s1 (kon_ch1s1),
- .ch2s1 (kon_ch2s1),
- .ch3s1 (kon_ch3s1),
- .ch4s1 (kon_ch4s1),
- .ch5s1 (kon_ch5s1),
-
- .ch0s2 (kon_ch0s2),
- .ch1s2 (kon_ch1s2),
- .ch2s2 (kon_ch2s2),
- .ch3s2 (kon_ch3s2),
- .ch4s2 (kon_ch4s2),
- .ch5s2 (kon_ch5s2),
-
- .ch0s3 (kon_ch0s3),
- .ch1s3 (kon_ch1s3),
- .ch2s3 (kon_ch2s3),
- .ch3s3 (kon_ch3s3),
- .ch4s3 (kon_ch4s3),
- .ch5s3 (kon_ch5s3),
-
- .ch0s4 (kon_ch0s4),
- .ch1s4 (kon_ch1s4),
- .ch2s4 (kon_ch2s4),
- .ch3s4 (kon_ch3s4),
- .ch4s4 (kon_ch4s4),
- .ch5s4 (kon_ch5s4)
-);
-
-/* Dump all registers on request */
-integer fmmr;
-initial begin
- fmmr=$fopen("mmr_dump.log","w");
-end
-
-always @(posedge clk )
-if (mmr_dump ) begin
- $fdisplay( fmmr, "-------------------------------");
- // Channel 0
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch0s1, fnum_ch0s1, rl_ch0s1, fb_ch0s1, alg_ch0s1,
- dt1_ch0s1, mul_ch0s1, tl_ch0s1, ar_ch0s1, d1r_ch0s1,
- d2r_ch0s1, rr_ch0s1, d1l_ch0s1, ks_ch0s1, ssg_ch0s1,
- kon_ch0s1 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch0s2, fnum_ch0s2, rl_ch0s2, fb_ch0s2, alg_ch0s2,
- dt1_ch0s2, mul_ch0s2, tl_ch0s2, ar_ch0s2, d1r_ch0s2,
- d2r_ch0s2, rr_ch0s2, d1l_ch0s2, ks_ch0s2, ssg_ch0s2,
- kon_ch0s2 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch0s1, fnum_ch0s3, rl_ch0s3, fb_ch0s3, alg_ch0s3,
- dt1_ch0s3, mul_ch0s3, tl_ch0s3, ar_ch0s3, d1r_ch0s3,
- d2r_ch0s3, rr_ch0s3, d1l_ch0s3, ks_ch0s3, ssg_ch0s3,
- kon_ch0s3 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch0s4, fnum_ch0s4, rl_ch0s4, fb_ch0s4, alg_ch0s4,
- dt1_ch0s4, mul_ch0s4, tl_ch0s4, ar_ch0s4, d1r_ch0s4,
- d2r_ch0s4, rr_ch0s4, d1l_ch0s4, ks_ch0s4, ssg_ch0s4,
- kon_ch0s4 );
- // Channel 1
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch1s1, fnum_ch1s1, rl_ch1s1, fb_ch1s1, alg_ch1s1,
- dt1_ch1s1, mul_ch1s1, tl_ch1s1, ar_ch1s1, d1r_ch1s1,
- d2r_ch1s1, rr_ch1s1, d1l_ch1s1, ks_ch1s1, ssg_ch1s1,
- kon_ch1s1 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch1s2, fnum_ch1s2, rl_ch1s2, fb_ch1s2, alg_ch1s2,
- dt1_ch1s2, mul_ch1s2, tl_ch1s2, ar_ch1s2, d1r_ch1s2,
- d2r_ch1s2, rr_ch1s2, d1l_ch1s2, ks_ch1s2, ssg_ch1s2,
- kon_ch1s2 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch1s3, fnum_ch1s3, rl_ch1s3, fb_ch1s3, alg_ch1s3,
- dt1_ch1s3, mul_ch1s3, tl_ch1s3, ar_ch1s3, d1r_ch1s3,
- d2r_ch1s3, rr_ch1s3, d1l_ch1s3, ks_ch1s3, ssg_ch1s3,
- kon_ch1s3 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch1s4, fnum_ch1s4, rl_ch1s4, fb_ch1s4, alg_ch1s4,
- dt1_ch1s4, mul_ch1s4, tl_ch1s4, ar_ch1s4, d1r_ch1s4,
- d2r_ch1s4, rr_ch1s4, d1l_ch1s4, ks_ch1s4, ssg_ch1s4,
- kon_ch1s4 );
- // Channel 2
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch2s1, fnum_ch2s1, rl_ch2s1, fb_ch2s1, alg_ch2s1,
- dt1_ch2s1, mul_ch2s1, tl_ch2s1, ar_ch2s1, d1r_ch2s1,
- d2r_ch2s1, rr_ch2s1, d1l_ch2s1, ks_ch2s1, ssg_ch2s1,
- kon_ch2s1 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch2s2, fnum_ch2s2, rl_ch2s2, fb_ch2s2, alg_ch2s2,
- dt1_ch2s2, mul_ch2s2, tl_ch2s2, ar_ch2s2, d1r_ch2s2,
- d2r_ch2s2, rr_ch2s2, d1l_ch2s2, ks_ch2s2, ssg_ch2s2,
- kon_ch2s2 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch2s3, fnum_ch2s3, rl_ch2s3, fb_ch2s3, alg_ch2s3,
- dt1_ch2s3, mul_ch2s3, tl_ch2s3, ar_ch2s3, d1r_ch2s3,
- d2r_ch2s3, rr_ch2s3, d1l_ch2s3, ks_ch2s3, ssg_ch2s3,
- kon_ch2s3 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch2s4, fnum_ch2s4, rl_ch2s4, fb_ch2s4, alg_ch2s4,
- dt1_ch2s4, mul_ch2s4, tl_ch2s4, ar_ch2s4, d1r_ch2s4,
- d2r_ch2s4, rr_ch2s4, d1l_ch2s4, ks_ch2s4, ssg_ch2s4,
- kon_ch2s4 );
- // Channel 3
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch3s1, fnum_ch3s1, rl_ch3s1, fb_ch3s1, alg_ch3s1,
- dt1_ch3s1, mul_ch3s1, tl_ch3s1, ar_ch3s1, d1r_ch3s1,
- d2r_ch3s1, rr_ch3s1, d1l_ch3s1, ks_ch3s1, ssg_ch3s1,
- kon_ch3s1 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch3s2, fnum_ch3s2, rl_ch3s2, fb_ch3s2, alg_ch3s2,
- dt1_ch3s2, mul_ch3s2, tl_ch3s2, ar_ch3s2, d1r_ch3s2,
- d2r_ch3s2, rr_ch3s2, d1l_ch3s2, ks_ch3s2, ssg_ch3s2,
- kon_ch3s2 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch3s3, fnum_ch3s3, rl_ch3s3, fb_ch3s3, alg_ch3s3,
- dt1_ch3s3, mul_ch3s3, tl_ch3s3, ar_ch3s3, d1r_ch3s3,
- d2r_ch3s3, rr_ch3s3, d1l_ch3s3, ks_ch3s3, ssg_ch3s3,
- kon_ch3s3 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch3s4, fnum_ch3s4, rl_ch3s4, fb_ch3s4, alg_ch3s4,
- dt1_ch3s4, mul_ch3s4, tl_ch3s4, ar_ch3s4, d1r_ch3s4,
- d2r_ch3s4, rr_ch3s4, d1l_ch3s4, ks_ch3s4, ssg_ch3s4,
- kon_ch3s4 );
- // Channel 4
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch4s1, fnum_ch4s1, rl_ch4s1, fb_ch4s1, alg_ch4s1,
- dt1_ch4s1, mul_ch4s1, tl_ch4s1, ar_ch4s1, d1r_ch4s1,
- d2r_ch4s1, rr_ch4s1, d1l_ch4s1, ks_ch4s1, ssg_ch4s1,
- kon_ch4s1 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch4s2, fnum_ch4s2, rl_ch4s2, fb_ch4s2, alg_ch4s2,
- dt1_ch4s2, mul_ch4s2, tl_ch4s2, ar_ch4s2, d1r_ch4s2,
- d2r_ch4s2, rr_ch4s2, d1l_ch4s2, ks_ch4s2, ssg_ch4s2,
- kon_ch4s2 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch4s3, fnum_ch4s3, rl_ch4s3, fb_ch4s3, alg_ch4s3,
- dt1_ch4s3, mul_ch4s3, tl_ch4s3, ar_ch4s3, d1r_ch4s3,
- d2r_ch4s3, rr_ch4s3, d1l_ch4s3, ks_ch4s3, ssg_ch4s3,
- kon_ch4s3 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch4s4, fnum_ch4s4, rl_ch4s4, fb_ch4s4, alg_ch4s4,
- dt1_ch4s4, mul_ch4s4, tl_ch4s4, ar_ch4s4, d1r_ch4s4,
- d2r_ch4s4, rr_ch4s4, d1l_ch4s4, ks_ch4s4, ssg_ch4s4,
- kon_ch4s4 );
- // Channel 5
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch5s1, fnum_ch5s1, rl_ch5s1, fb_ch5s1, alg_ch5s1,
- dt1_ch5s1, mul_ch5s1, tl_ch5s1, ar_ch5s1, d1r_ch5s1,
- d2r_ch5s1, rr_ch5s1, d1l_ch5s1, ks_ch5s1, ssg_ch5s1,
- kon_ch5s1 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch5s2, fnum_ch5s2, rl_ch5s2, fb_ch5s2, alg_ch5s2,
- dt1_ch5s2, mul_ch5s2, tl_ch5s2, ar_ch5s2, d1r_ch5s2,
- d2r_ch5s2, rr_ch5s2, d1l_ch5s2, ks_ch5s2, ssg_ch5s2,
- kon_ch5s2 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch5s3, fnum_ch5s3, rl_ch5s3, fb_ch5s3, alg_ch5s3,
- dt1_ch5s3, mul_ch5s3, tl_ch5s3, ar_ch5s3, d1r_ch5s3,
- d2r_ch5s3, rr_ch5s3, d1l_ch5s3, ks_ch5s3, ssg_ch5s3,
- kon_ch5s3 );
- $fdisplay( fmmr, "%x %x %x %x %x, %x %x %x %x %x %x, %x %x %x %x %x",
- block_ch5s4, fnum_ch5s4, rl_ch5s4, fb_ch5s4, alg_ch5s4,
- dt1_ch5s4, mul_ch5s4, tl_ch5s4, ar_ch5s4, d1r_ch5s4,
- d2r_ch5s4, rr_ch5s4, d1l_ch5s4, ks_ch5s4, ssg_ch5s4,
- kon_ch5s4 );
-end
-/* verilator lint_on PINMISSING */
-`endif
-
diff --git a/rtl/sound/jt12/jt12_mod.v b/rtl/sound/jt12/jt12_mod.v
index a057f8f..2e7bef3 100644
--- a/rtl/sound/jt12/jt12_mod.v
+++ b/rtl/sound/jt12/jt12_mod.v
@@ -1,4 +1,3 @@
-`timescale 1ns / 1ps
/* This file is part of JT12.
@@ -140,16 +139,14 @@ generate
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
+// 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
endmodule
diff --git a/rtl/sound/jt12/jt12_op.v b/rtl/sound/jt12/jt12_op.v
index c9a406e..d0d2981 100644
--- a/rtl/sound/jt12/jt12_op.v
+++ b/rtl/sound/jt12/jt12_op.v
@@ -1,4 +1,3 @@
-`timescale 1ns / 1ps
/* This file is part of JT12.
@@ -29,7 +28,7 @@
module jt12_op(
input rst,
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input [9:0] pg_phase_VIII,
input [9:0] eg_atten_IX, // output from envelope generator
input [2:0] fb_II, // voice feedback
@@ -51,6 +50,8 @@ module jt12_op(
output signed [13:0] full_result
);
+parameter num_ch = 6;
+
/* enters exits
S1 S2
S3 S4
@@ -64,8 +65,6 @@ reg [11:0] atten_internal_IX;
assign op_result = op_result_internal[13:5];
assign full_result = op_result_internal;
-parameter num_ch = 6;
-
reg signbit_IX, signbit_X, signbit_XI;
reg [11:0] totalatten_X;
@@ -271,235 +270,62 @@ always @(posedge clk) if( clk_en ) begin
end
`ifdef SIMULATION
-/* verilator lint_off PINMISSING */
-reg [4:0] sep24_cnt;
+reg signed [13:0] op_sep2_0;
+reg signed [13:0] op_sep4_0;
+reg signed [13:0] op_sep5_0;
+reg signed [13:0] op_sep6_0;
+reg signed [13:0] op_sep0_0;
+reg signed [13:0] op_sep1_0;
+reg signed [13:0] op_sep2_1;
+reg signed [13:0] op_sep4_1;
+reg signed [13:0] op_sep5_1;
+reg signed [13:0] op_sep6_1;
+reg signed [13:0] op_sep0_1;
+reg signed [13:0] op_sep1_1;
+reg signed [13:0] op_sep2_2;
+reg signed [13:0] op_sep4_2;
+reg signed [13:0] op_sep5_2;
+reg signed [13:0] op_sep6_2;
+reg signed [13:0] op_sep0_2;
+reg signed [13:0] op_sep1_2;
+reg signed [13:0] op_sep2_3;
+reg signed [13:0] op_sep4_3;
+reg signed [13:0] op_sep5_3;
+reg signed [13:0] op_sep6_3;
+reg signed [13:0] op_sep0_3;
+reg signed [13:0] op_sep1_3;
+reg [ 4:0] sepcnt;
-wire signed [13:0] op_ch0s1, op_ch1s1, op_ch2s1, op_ch3s1,
- op_ch4s1, op_ch5s1, op_ch0s2, op_ch1s2,
- op_ch2s2, op_ch3s2, op_ch4s2, op_ch5s2,
- op_ch0s3, op_ch1s3, op_ch2s3, op_ch3s3,
- op_ch4s3, op_ch5s3, op_ch0s4, op_ch1s4,
- op_ch2s4, op_ch3s4, op_ch4s4, op_ch5s4;
-
-always @(posedge clk ) if( clk_en ) begin
- sep24_cnt <= !zero ? sep24_cnt+1'b1 : 5'd0;
+always @(posedge clk) if(clk_en) begin
+ sepcnt <= zero ? 5'd0 : sepcnt+5'd1;
+ case( (sepcnt+14)%24 )
+ 0: op_sep0_0 <= op_XII;
+ 1: op_sep1_0 <= op_XII;
+ 2: op_sep2_0 <= op_XII;
+ 3: op_sep4_0 <= op_XII;
+ 4: op_sep5_0 <= op_XII;
+ 5: op_sep6_0 <= op_XII;
+ 6: op_sep0_2 <= op_XII;
+ 7: op_sep1_2 <= op_XII;
+ 8: op_sep2_2 <= op_XII;
+ 9: op_sep4_2 <= op_XII;
+ 10: op_sep5_2 <= op_XII;
+ 11: op_sep6_2 <= op_XII;
+ 12: op_sep0_1 <= op_XII;
+ 13: op_sep1_1 <= op_XII;
+ 14: op_sep2_1 <= op_XII;
+ 15: op_sep4_1 <= op_XII;
+ 16: op_sep5_1 <= op_XII;
+ 17: op_sep6_1 <= op_XII;
+ 18: op_sep0_3 <= op_XII;
+ 19: op_sep1_3 <= op_XII;
+ 20: op_sep2_3 <= op_XII;
+ 21: op_sep4_3 <= op_XII;
+ 22: op_sep5_3 <= op_XII;
+ 23: op_sep6_3 <= op_XII;
+ endcase
end
-sep24 #( .width(14), .pos0(13)) opsep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( op_result_internal ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (op_ch0s1),
- .ch1s1 (op_ch1s1),
- .ch2s1 (op_ch2s1),
- .ch3s1 (op_ch3s1),
- .ch4s1 (op_ch4s1),
- .ch5s1 (op_ch5s1),
-
- .ch0s2 (op_ch0s2),
- .ch1s2 (op_ch1s2),
- .ch2s2 (op_ch2s2),
- .ch3s2 (op_ch3s2),
- .ch4s2 (op_ch4s2),
- .ch5s2 (op_ch5s2),
-
- .ch0s3 (op_ch0s3),
- .ch1s3 (op_ch1s3),
- .ch2s3 (op_ch2s3),
- .ch3s3 (op_ch3s3),
- .ch4s3 (op_ch4s3),
- .ch5s3 (op_ch5s3),
-
- .ch0s4 (op_ch0s4),
- .ch1s4 (op_ch1s4),
- .ch2s4 (op_ch2s4),
- .ch3s4 (op_ch3s4),
- .ch4s4 (op_ch4s4),
- .ch5s4 (op_ch5s4)
-);
-
-wire signed [8:0] acc_ch0s1, acc_ch1s1, acc_ch2s1, acc_ch3s1,
- acc_ch4s1, acc_ch5s1, acc_ch0s2, acc_ch1s2,
- acc_ch2s2, acc_ch3s2, acc_ch4s2, acc_ch5s2,
- acc_ch0s3, acc_ch1s3, acc_ch2s3, acc_ch3s3,
- acc_ch4s3, acc_ch5s3, acc_ch0s4, acc_ch1s4,
- acc_ch2s4, acc_ch3s4, acc_ch4s4, acc_ch5s4;
-
-sep24 #( .width(9), .pos0(13)) accsep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( op_result_internal[13:5] ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (acc_ch0s1),
- .ch1s1 (acc_ch1s1),
- .ch2s1 (acc_ch2s1),
- .ch3s1 (acc_ch3s1),
- .ch4s1 (acc_ch4s1),
- .ch5s1 (acc_ch5s1),
-
- .ch0s2 (acc_ch0s2),
- .ch1s2 (acc_ch1s2),
- .ch2s2 (acc_ch2s2),
- .ch3s2 (acc_ch3s2),
- .ch4s2 (acc_ch4s2),
- .ch5s2 (acc_ch5s2),
-
- .ch0s3 (acc_ch0s3),
- .ch1s3 (acc_ch1s3),
- .ch2s3 (acc_ch2s3),
- .ch3s3 (acc_ch3s3),
- .ch4s3 (acc_ch4s3),
- .ch5s3 (acc_ch5s3),
-
- .ch0s4 (acc_ch0s4),
- .ch1s4 (acc_ch1s4),
- .ch2s4 (acc_ch2s4),
- .ch3s4 (acc_ch3s4),
- .ch4s4 (acc_ch4s4),
- .ch5s4 (acc_ch5s4)
-);
-
-wire signed [9:0] pm_ch0s1, pm_ch1s1, pm_ch2s1, pm_ch3s1,
- pm_ch4s1, pm_ch5s1, pm_ch0s2, pm_ch1s2,
- pm_ch2s2, pm_ch3s2, pm_ch4s2, pm_ch5s2,
- pm_ch0s3, pm_ch1s3, pm_ch2s3, pm_ch3s3,
- pm_ch4s3, pm_ch5s3, pm_ch0s4, pm_ch1s4,
- pm_ch2s4, pm_ch3s4, pm_ch4s4, pm_ch5s4;
-
-
-sep24 #( .width(10), .pos0( 18 ) ) pmsep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( phasemod_VIII ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (pm_ch0s1),
- .ch1s1 (pm_ch1s1),
- .ch2s1 (pm_ch2s1),
- .ch3s1 (pm_ch3s1),
- .ch4s1 (pm_ch4s1),
- .ch5s1 (pm_ch5s1),
-
- .ch0s2 (pm_ch0s2),
- .ch1s2 (pm_ch1s2),
- .ch2s2 (pm_ch2s2),
- .ch3s2 (pm_ch3s2),
- .ch4s2 (pm_ch4s2),
- .ch5s2 (pm_ch5s2),
-
- .ch0s3 (pm_ch0s3),
- .ch1s3 (pm_ch1s3),
- .ch2s3 (pm_ch2s3),
- .ch3s3 (pm_ch3s3),
- .ch4s3 (pm_ch4s3),
- .ch5s3 (pm_ch5s3),
-
- .ch0s4 (pm_ch0s4),
- .ch1s4 (pm_ch1s4),
- .ch2s4 (pm_ch2s4),
- .ch3s4 (pm_ch3s4),
- .ch4s4 (pm_ch4s4),
- .ch5s4 (pm_ch5s4)
-);
-
-wire [9:0] phase_ch0s1, phase_ch1s1, phase_ch2s1, phase_ch3s1,
- phase_ch4s1, phase_ch5s1, phase_ch0s2, phase_ch1s2,
- phase_ch2s2, phase_ch3s2, phase_ch4s2, phase_ch5s2,
- phase_ch0s3, phase_ch1s3, phase_ch2s3, phase_ch3s3,
- phase_ch4s3, phase_ch5s3, phase_ch0s4, phase_ch1s4,
- phase_ch2s4, phase_ch3s4, phase_ch4s4, phase_ch5s4;
-
-
-sep24 #( .width(10), .pos0( 18 ) ) phsep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( phase ),
- .mask ( 24'd0 ),
- .cnt ( sep24_cnt ),
-
- .ch0s1 (phase_ch0s1),
- .ch1s1 (phase_ch1s1),
- .ch2s1 (phase_ch2s1),
- .ch3s1 (phase_ch3s1),
- .ch4s1 (phase_ch4s1),
- .ch5s1 (phase_ch5s1),
-
- .ch0s2 (phase_ch0s2),
- .ch1s2 (phase_ch1s2),
- .ch2s2 (phase_ch2s2),
- .ch3s2 (phase_ch3s2),
- .ch4s2 (phase_ch4s2),
- .ch5s2 (phase_ch5s2),
-
- .ch0s3 (phase_ch0s3),
- .ch1s3 (phase_ch1s3),
- .ch2s3 (phase_ch2s3),
- .ch3s3 (phase_ch3s3),
- .ch4s3 (phase_ch4s3),
- .ch5s3 (phase_ch5s3),
-
- .ch0s4 (phase_ch0s4),
- .ch1s4 (phase_ch1s4),
- .ch2s4 (phase_ch2s4),
- .ch3s4 (phase_ch3s4),
- .ch4s4 (phase_ch4s4),
- .ch5s4 (phase_ch5s4)
-);
-
-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;
-
-
-sep24 #( .width(10), .pos0(17) ) egsep
-(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .mixed ( eg_atten_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)
-);
-/* verilator lint_on PINMISSING */
`endif
-
endmodule
diff --git a/rtl/sound/jt12/jt12_pcm.v b/rtl/sound/jt12/jt12_pcm.v
deleted file mode 100644
index 88724f8..0000000
--- a/rtl/sound/jt12/jt12_pcm.v
+++ /dev/null
@@ -1,109 +0,0 @@
-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
\ No newline at end of file
diff --git a/rtl/sound/jt12/jt12_pg.v b/rtl/sound/jt12/jt12_pg.v
index cf6b004..913a739 100644
--- a/rtl/sound/jt12/jt12_pg.v
+++ b/rtl/sound/jt12/jt12_pg.v
@@ -24,7 +24,6 @@ http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc
*/
-`timescale 1ns / 1ps
/*
@@ -34,7 +33,7 @@ http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc
module jt12_pg(
input clk,
- input clk_en,
+ input clk_en /* synthesis direct_enable */,
input rst,
// Channel frequency
input [10:0] fnum_I,
diff --git a/rtl/sound/jt12/jt12_pg_sum.v b/rtl/sound/jt12/jt12_pg_sum.v
index ca79c2e..6369c53 100644
--- a/rtl/sound/jt12/jt12_pg_sum.v
+++ b/rtl/sound/jt12/jt12_pg_sum.v
@@ -1,49 +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 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.
+ 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 .
-
- Author: Jose Tejada Gomez. Twitter: @topapate
- Version: 1.0
- Date: 2-11-2018
-
- Based on information posted by Nemesis on:
+ You should have received a copy of the GNU General Public License
+ along with JT12. If not, see .
+
+ 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
-
- */
+ 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,
+ 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
+ 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];
+ 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
\ No newline at end of file
diff --git a/rtl/sound/jt12/jt12_pm.v b/rtl/sound/jt12/jt12_pm.v
index e233f94..acfafdc 100644
--- a/rtl/sound/jt12/jt12_pm.v
+++ b/rtl/sound/jt12/jt12_pm.v
@@ -17,10 +17,7 @@
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.
@@ -38,18 +35,144 @@ 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_lut [0:63];
+reg [2: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);
+ lfo_sh1_lut[6'h00] = 3'd7;
+ lfo_sh1_lut[6'h01] = 3'd7;
+ lfo_sh1_lut[6'h02] = 3'd7;
+ lfo_sh1_lut[6'h03] = 3'd7;
+ lfo_sh1_lut[6'h04] = 3'd7;
+ lfo_sh1_lut[6'h05] = 3'd7;
+ lfo_sh1_lut[6'h06] = 3'd7;
+ lfo_sh1_lut[6'h07] = 3'd7;
+ lfo_sh1_lut[6'h08] = 3'd7;
+ lfo_sh1_lut[6'h09] = 3'd7;
+ lfo_sh1_lut[6'h0A] = 3'd7;
+ lfo_sh1_lut[6'h0B] = 3'd7;
+ lfo_sh1_lut[6'h0C] = 3'd7;
+ lfo_sh1_lut[6'h0D] = 3'd7;
+ lfo_sh1_lut[6'h0E] = 3'd7;
+ lfo_sh1_lut[6'h0F] = 3'd7;
+ lfo_sh1_lut[6'h10] = 3'd7;
+ lfo_sh1_lut[6'h11] = 3'd7;
+ lfo_sh1_lut[6'h12] = 3'd7;
+ lfo_sh1_lut[6'h13] = 3'd7;
+ lfo_sh1_lut[6'h14] = 3'd7;
+ lfo_sh1_lut[6'h15] = 3'd7;
+ lfo_sh1_lut[6'h16] = 3'd1;
+ lfo_sh1_lut[6'h17] = 3'd1;
+ lfo_sh1_lut[6'h18] = 3'd7;
+ lfo_sh1_lut[6'h19] = 3'd7;
+ lfo_sh1_lut[6'h1A] = 3'd7;
+ lfo_sh1_lut[6'h1B] = 3'd7;
+ lfo_sh1_lut[6'h1C] = 3'd1;
+ lfo_sh1_lut[6'h1D] = 3'd1;
+ lfo_sh1_lut[6'h1E] = 3'd1;
+ lfo_sh1_lut[6'h1F] = 3'd1;
+ lfo_sh1_lut[6'h20] = 3'd7;
+ lfo_sh1_lut[6'h21] = 3'd7;
+ lfo_sh1_lut[6'h22] = 3'd7;
+ lfo_sh1_lut[6'h23] = 3'd1;
+ lfo_sh1_lut[6'h24] = 3'd1;
+ lfo_sh1_lut[6'h25] = 3'd1;
+ lfo_sh1_lut[6'h26] = 3'd1;
+ lfo_sh1_lut[6'h27] = 3'd0;
+ lfo_sh1_lut[6'h28] = 3'd7;
+ lfo_sh1_lut[6'h29] = 3'd7;
+ lfo_sh1_lut[6'h2A] = 3'd1;
+ lfo_sh1_lut[6'h2B] = 3'd1;
+ lfo_sh1_lut[6'h2C] = 3'd0;
+ lfo_sh1_lut[6'h2D] = 3'd0;
+ lfo_sh1_lut[6'h2E] = 3'd0;
+ lfo_sh1_lut[6'h2F] = 3'd0;
+ lfo_sh1_lut[6'h30] = 3'd7;
+ lfo_sh1_lut[6'h31] = 3'd7;
+ lfo_sh1_lut[6'h32] = 3'd1;
+ lfo_sh1_lut[6'h33] = 3'd1;
+ lfo_sh1_lut[6'h34] = 3'd0;
+ lfo_sh1_lut[6'h35] = 3'd0;
+ lfo_sh1_lut[6'h36] = 3'd0;
+ lfo_sh1_lut[6'h37] = 3'd0;
+ lfo_sh1_lut[6'h38] = 3'd7;
+ lfo_sh1_lut[6'h39] = 3'd7;
+ lfo_sh1_lut[6'h3A] = 3'd1;
+ lfo_sh1_lut[6'h3B] = 3'd1;
+ lfo_sh1_lut[6'h3C] = 3'd0;
+ lfo_sh1_lut[6'h3D] = 3'd0;
+ lfo_sh1_lut[6'h3E] = 3'd0;
+ lfo_sh1_lut[6'h3F] = 3'd0;
+ lfo_sh2_lut[6'h00] = 3'd7;
+ lfo_sh2_lut[6'h01] = 3'd7;
+ lfo_sh2_lut[6'h02] = 3'd7;
+ lfo_sh2_lut[6'h03] = 3'd7;
+ lfo_sh2_lut[6'h04] = 3'd7;
+ lfo_sh2_lut[6'h05] = 3'd7;
+ lfo_sh2_lut[6'h06] = 3'd7;
+ lfo_sh2_lut[6'h07] = 3'd7;
+ lfo_sh2_lut[6'h08] = 3'd7;
+ lfo_sh2_lut[6'h09] = 3'd7;
+ lfo_sh2_lut[6'h0A] = 3'd7;
+ lfo_sh2_lut[6'h0B] = 3'd7;
+ lfo_sh2_lut[6'h0C] = 3'd2;
+ lfo_sh2_lut[6'h0D] = 3'd2;
+ lfo_sh2_lut[6'h0E] = 3'd2;
+ lfo_sh2_lut[6'h0F] = 3'd2;
+ lfo_sh2_lut[6'h10] = 3'd7;
+ lfo_sh2_lut[6'h11] = 3'd7;
+ lfo_sh2_lut[6'h12] = 3'd7;
+ lfo_sh2_lut[6'h13] = 3'd2;
+ lfo_sh2_lut[6'h14] = 3'd2;
+ lfo_sh2_lut[6'h15] = 3'd2;
+ lfo_sh2_lut[6'h16] = 3'd7;
+ lfo_sh2_lut[6'h17] = 3'd7;
+ lfo_sh2_lut[6'h18] = 3'd7;
+ lfo_sh2_lut[6'h19] = 3'd7;
+ lfo_sh2_lut[6'h1A] = 3'd2;
+ lfo_sh2_lut[6'h1B] = 3'd2;
+ lfo_sh2_lut[6'h1C] = 3'd7;
+ lfo_sh2_lut[6'h1D] = 3'd7;
+ lfo_sh2_lut[6'h1E] = 3'd2;
+ lfo_sh2_lut[6'h1F] = 3'd2;
+ lfo_sh2_lut[6'h20] = 3'd7;
+ lfo_sh2_lut[6'h21] = 3'd7;
+ lfo_sh2_lut[6'h22] = 3'd2;
+ lfo_sh2_lut[6'h23] = 3'd7;
+ lfo_sh2_lut[6'h24] = 3'd7;
+ lfo_sh2_lut[6'h25] = 3'd7;
+ lfo_sh2_lut[6'h26] = 3'd2;
+ lfo_sh2_lut[6'h27] = 3'd7;
+ lfo_sh2_lut[6'h28] = 3'd7;
+ lfo_sh2_lut[6'h29] = 3'd7;
+ lfo_sh2_lut[6'h2A] = 3'd7;
+ lfo_sh2_lut[6'h2B] = 3'd2;
+ lfo_sh2_lut[6'h2C] = 3'd7;
+ lfo_sh2_lut[6'h2D] = 3'd7;
+ lfo_sh2_lut[6'h2E] = 3'd2;
+ lfo_sh2_lut[6'h2F] = 3'd1;
+ lfo_sh2_lut[6'h30] = 3'd7;
+ lfo_sh2_lut[6'h31] = 3'd7;
+ lfo_sh2_lut[6'h32] = 3'd7;
+ lfo_sh2_lut[6'h33] = 3'd2;
+ lfo_sh2_lut[6'h34] = 3'd7;
+ lfo_sh2_lut[6'h35] = 3'd7;
+ lfo_sh2_lut[6'h36] = 3'd2;
+ lfo_sh2_lut[6'h37] = 3'd1;
+ lfo_sh2_lut[6'h38] = 3'd7;
+ lfo_sh2_lut[6'h39] = 3'd7;
+ lfo_sh2_lut[6'h3A] = 3'd7;
+ lfo_sh2_lut[6'h3B] = 3'd2;
+ lfo_sh2_lut[6'h3C] = 3'd7;
+ lfo_sh2_lut[6'h3D] = 3'd7;
+ lfo_sh2_lut[6'h3E] = 3'd2;
+ lfo_sh2_lut[6'h3F] = 3'd1;
end
always @(*) begin
- lfo_sh1 = lfo_sh1_lut[{pms,index}][2:0];
- lfo_sh2 = lfo_sh2_lut[{pms,index}][2:0];
+ lfo_sh1 = lfo_sh1_lut[{pms,index}];
+ lfo_sh2 = lfo_sh2_lut[{pms,index}];
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 };
diff --git a/rtl/sound/jt12/jt12_reg.v b/rtl/sound/jt12/jt12_reg.v
index 08cee76..0b1b4e2 100644
--- a/rtl/sound/jt12/jt12_reg.v
+++ b/rtl/sound/jt12/jt12_reg.v
@@ -23,30 +23,35 @@
module jt12_reg(
input rst,
input clk,
- input clk_en,
- input [7:0] din,
+ input clk_en /* synthesis direct_enable */,
- input [2:0] ch,
+ input [2:0] ch, // channel to update
input [1:0] op,
input csm,
input flag_A,
input overflow_A,
- input up_keyon,
+ // channel udpates
+ input [2:0] ch_sel,
+ input [7:0] ch_din,
input up_alg,
input up_fnumlo,
+ // operator updates
+ input [7:0] din,
+ input up_keyon,
input up_pms,
input up_dt1,
input up_tl,
input up_ks_ar,
input up_amen_dr,
input up_sr,
-
input up_sl_rr,
input up_ssgeg,
- output reg ch6op, // 1 when the operator belongs to CH6
+ output reg ch6op, // 1 when the operator belongs to CH6
+ output reg [2:0] cur_ch,
+ output reg [1:0] cur_op,
// CH3 Effect-mode operation
input effect,
@@ -105,8 +110,8 @@ module jt12_reg(
parameter num_ch=6; // Use only 3 (YM2203/YM2610) or 6 (YM2612/YM2608)
-reg [1:0] next_op, cur_op;
-reg [2:0] next_ch, cur_ch;
+reg [1:0] next_op;
+reg [2:0] next_ch;
reg last;
`ifdef SIMULATION
@@ -117,6 +122,8 @@ reg last;
initial begin
cur_op = 2'd0;
cur_ch = 3'd0;
+ next_op = 2'd0;
+ next_ch = 3'd1;
last = 1'b0;
zero = 1'b1;
end
@@ -155,11 +162,9 @@ assign block_I =( {3{effect_on_s1}} & block_ch3op1 ) |
( {3{effect_on_s3}} & block_ch3op3 ) |
( {3{noeffect}} & block_I_raw );
-wire [2:0] ch_II, ch_III, ch_IV, ch_V, ch_VI;
-
wire [4:0] req_opch_I = { op, ch };
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 #(.num_ch(num_ch)) u_opch_II ( .chin(req_opch_I ), .chout(req_opch_II ) );
jt12_sumch #(.num_ch(num_ch)) u_opch_III( .chin(req_opch_II ), .chout(req_opch_III) );
@@ -179,24 +184,6 @@ wire update_op_IV = cur == req_opch_IV;
// key on/off
wire [3:0] keyon_op = din[7:4];
wire [2:0] keyon_ch = din[2:0];
-// channel data
-//wire [1:0] rl_in = din[7:6];
-wire [2:0] fb_in = din[5:3];
-wire [2:0] alg_in = din[2:0];
-wire [2:0] pms_in = din[2:0];
-wire [1:0] ams_in = din[5:4];
-wire [7:0] fnlo_in = din;
-
-
-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_fnumlo_ch=up_fnumlo & update_ch_I;
-wire up_pms_ch = up_pms & update_ch_I;
-wire up_ams_ch = up_pms & update_ch_IV;
always @(*) begin
// next = cur==5'd23 ? 5'd0 : cur +1'b1;
@@ -216,6 +203,7 @@ always @(posedge clk) begin : up_counter
end
end
+`ifndef NOFM
jt12_kon #(.num_ch(num_ch)) u_kon(
.rst ( rst ),
.clk ( clk ),
@@ -325,46 +313,27 @@ assign { tl_IV, dt1_I, mul_II, ks_II,
// memory for CH registers
-// Block/fnum data is latched until fnum low byte is written to
-// Trying to synthesize this memory as M-9K RAM in Altera devices
-// 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.
-localparam regch_width=25;
-wire [regch_width-1:0] regch_out;
-wire [regch_width-1:0] regch_in = {
- up_fnumlo_ch? { latch_fnum, fnlo_in } : { block_I_raw, fnum_I_raw }, // 14
- up_alg_ch ? { fb_in, alg_in } : { fb_I, alg_I },//3+3
- up_ams_ch ? ams_in : ams_IV, //2
- up_pms_ch ? pms_in : pms_I //3
-};
+jt12_reg_ch #(.NUM_CH(num_ch)) u_regch(
+ .rst ( rst ),
+ .clk ( clk ),
+ .cen ( clk_en ),
+ .din ( ch_din ),
-assign { block_I_raw, fnum_I_raw,
- fb_I, alg_I, ams_IV, pms_I } = regch_out;
+ .up_ch ( ch_sel ),
+ .latch_fnum ( latch_fnum ),
+ .up_fnumlo ( up_fnumlo ),
+ .up_alg ( up_alg ),
+ .up_pms ( up_pms ),
-jt12_sh_rst #(.width(regch_width),.stages(num_ch)) u_regch(
- .clk ( clk ),
- .clk_en ( clk_en ),
- .rst ( rst ),
- .din ( regch_in ),
- .drop ( regch_out )
+ .ch ( next_ch ), // next active channel
+ .block ( block_I_raw ),
+ .fnum ( fnum_I_raw ),
+ .fb ( fb_I ),
+ .alg ( alg_I ),
+ .rl ( rl ),
+ .ams_IV ( ams_IV ),
+ .pms ( pms_I )
);
-generate
-if( num_ch==6 ) begin
- // RL is on a different register to
- // have the reset to 1
- 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_en ( clk_en ),
- .rst ( rst ),
- .din ( up_pms_ch ? rl_in : rl ),
- .drop ( rl )
- );
-end else begin // YM2203 has no stereo output
- assign rl=2'b11;
-end
-
-endgenerate
-
+`endif
endmodule
diff --git a/rtl/sound/jt12/jt12_reg_ch.v b/rtl/sound/jt12/jt12_reg_ch.v
new file mode 100644
index 0000000..d3f5b2e
--- /dev/null
+++ b/rtl/sound/jt12/jt12_reg_ch.v
@@ -0,0 +1,128 @@
+/* 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 .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 23-10-2019
+ */
+
+// Channel data is not stored in a CSR as operators
+// Proof of that is the Splatter House arcade writes
+// channel and operator data in two consequitive accesses
+// without enough time in between to have the eight
+// channels go through the CSR. So the channel data
+// cannot be CSR, but regular registers.
+module jt12_reg_ch(
+ input rst,
+ input clk,
+ input cen,
+ input [ 7:0] din,
+
+ input [ 2:0] up_ch,
+ input [ 5:0] latch_fnum,
+ input up_fnumlo,
+ input up_alg,
+ input up_pms,
+
+ input [ 2:0] ch, // next active channel
+ output reg [ 2:0] block,
+ output reg [10:0] fnum,
+ output reg [ 2:0] fb,
+ output reg [ 2:0] alg,
+ output reg [ 1:0] rl,
+ output reg [ 1:0] ams_IV,
+ output reg [ 2:0] pms
+);
+
+parameter NUM_CH=6;
+localparam M=NUM_CH==3?2:3;
+
+reg [ 2:0] reg_block[0:NUM_CH-1];
+reg [10:0] reg_fnum [0:NUM_CH-1];
+reg [ 2:0] reg_fb [0:NUM_CH-1];
+reg [ 2:0] reg_alg [0:NUM_CH-1];
+reg [ 1:0] reg_rl [0:NUM_CH-1];
+reg [ 1:0] reg_ams [0:NUM_CH-1];
+reg [ 2:0] reg_pms [0:NUM_CH-1];
+reg [ 2:0] ch_IV;
+
+wire [M-1:0] ch_sel, out_sel;
+
+function [M-1:0] chtr( input [2:0] chin );
+reg [2:0] aux;
+begin
+ aux = chin[M-1] ? {1'b0,chin[1:0]}+3'd3 : // upper channels
+ {1'b0,chin[1:0]}; // lower
+ chtr = NUM_CH==3 ? chin[M-1:0] : aux[M-1:0];
+
+end
+endfunction
+
+assign ch_sel = chtr(up_ch);
+assign out_sel = chtr(ch);
+
+integer i;
+/* verilator lint_off WIDTHEXPAND */
+always @* begin
+ ch_IV = ch;
+ if( NUM_CH==6 )
+ case(out_sel)
+ 0: ch_IV = 3;
+ 1: ch_IV = 4;
+ 2: ch_IV = 5;
+ 3: ch_IV = 0;
+ 4: ch_IV = 1;
+ 5: ch_IV = 2;
+ default: ch_IV = 0;
+ endcase
+end
+/* verilator lint_on WIDTHEXPAND */
+
+always @(posedge clk) if(cen) begin
+ block <= reg_block[out_sel];
+ fnum <= reg_fnum [out_sel];
+ fb <= reg_fb [out_sel];
+ alg <= reg_alg [out_sel];
+ rl <= reg_rl [out_sel];
+ ams_IV<= reg_ams [ch_IV[M-1:0]];
+ pms <= reg_pms [out_sel];
+ if( NUM_CH==3 ) rl <= 3; // YM2203 has no stereo output
+end
+
+always @(posedge clk, posedge rst) begin
+ if( rst ) for(i=0;i.
+ You should have received a copy of the GNU General Public License
+ along with JT12. If not, see .
- Author: Jose Tejada Gomez. Twitter: @topapate
- Version: 1.0
- Date: 14-2-2017
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 14-2-2017
- YM3438_APL.pdf
- Timer A = 144*(1024-NA)/Phi M
- Timer B = 2304*(256-NB)/Phi M
- */
+ YM3438_APL.pdf
+ Timer A = 144*(1024-NA)/Phi M
+ Timer B = 2304*(256-NB)/Phi M
+ */
-`timescale 1ns / 1ps
module jt12_timers(
- input clk,
- input rst,
- input clk_en, // clock enable
- input [9:0] value_A,
- input [7:0] value_B,
- input load_A,
- input load_B,
- input clr_flag_A,
- input clr_flag_B,
- input enable_irq_A,
- input enable_irq_B,
- output flag_A,
- output flag_B,
- output overflow_A,
- output irq_n
+ input clk,
+ input rst,
+ input clk_en /* synthesis direct_enable */,
+ input zero,
+ input [9:0] value_A,
+ input [7:0] value_B,
+ input load_A,
+ input load_B,
+ input clr_flag_A,
+ input clr_flag_B,
+ input enable_irq_A,
+ input enable_irq_B,
+ output flag_A,
+ output flag_B,
+ output overflow_A,
+ output irq_n
);
+parameter num_ch = 6;
+
assign irq_n = ~( (flag_A&enable_irq_A) | (flag_B&enable_irq_B) );
-jt12_timer #(.mult_width(5), .mult_max(24), .counter_width(10))
-timer_A(
- .clk ( clk ),
- .rst ( rst ),
- .clk_en ( clk_en ),
- .start_value( value_A ),
- .load ( load_A ),
- .clr_flag ( clr_flag_A),
- .flag ( flag_A ),
- .overflow ( overflow_A)
-);
+/*
+reg zero2;
-jt12_timer #(.mult_width(9), .mult_max(384), .counter_width(8))
-timer_B(
- .clk ( clk ),
- .rst ( rst ),
- .clk_en ( clk_en ),
- .start_value( value_B ),
- .load ( load_B ),
- .clr_flag ( clr_flag_B),
- .flag ( flag_B ),
- .overflow ( )
-);
-
-endmodule
-
-module jt12_timer #(parameter counter_width = 10, mult_width=5, mult_max=4 )
-(
- input clk,
- input rst,
-(* direct_enable *) input clk_en,
- input [counter_width-1:0] start_value,
- input load,
- input clr_flag,
- output reg flag,
- output reg overflow
-);
-
-reg [ mult_width-1:0] mult;
-reg [counter_width-1:0] cnt;
-
-always@(posedge clk)
- if( clr_flag || rst)
- flag <= 1'b0;
- else if(overflow) flag<=1'b1;
-
-reg [mult_width+counter_width-1:0] next, init;
-
-always @(*) begin
- if( mult.
-
+
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
-
+ 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
+ (* direct_enable *) input cen, // optional clock enable, if 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,
+ // Configuration
+ input en_hifi_pcm, // high to enable PCM interpolation on YM2612 mode
+ // ADPCM pins
+ output [19:0] adpcma_addr, // real hardware has 10 pins multiplexed through RMPX pin
+ output [ 3:0] adpcma_bank,
+ output adpcma_roe_n, // ADPCM-A ROM output enable
+ input [ 7:0] adpcma_data, // Data from RAM
+ output [23:0] adpcmb_addr, // real hardware has 12 pins multiplexed through PMPX pin
+ input [ 7:0] adpcmb_data,
+ output adpcmb_roe_n, // ADPCM-B ROM output enable
+ // I/O pins used by YM2203 embedded YM2149 chip
+ input [7:0] IOA_in,
+ input [7:0] IOB_in,
+ output [7:0] IOA_out,
+ output [7:0] IOB_out,
+ output IOA_oe,
+ output IOB_oe,
// 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,
+ output signed [15:0] adpcmA_l,
+ output signed [15:0] adpcmA_r,
+ output signed [15:0] adpcmB_l,
+ output signed [15:0] adpcmB_r,
// 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
+ output snd_sample,
+ input [ 5:0] ch_enable, // ADPCM-A channels
+ input [ 7:0] debug_bus,
+ output [ 7:0] debug_view
);
-parameter use_lfo=1, use_ssg=0, num_ch=6, use_pcm=1, use_lr=1; // defaults to YM2612
+// parameters to select the features for each chip type
+// defaults to YM2612
+parameter use_lfo=1, use_ssg=0, num_ch=6, use_pcm=1;
+parameter use_adpcm=0;
+parameter JT49_DIV=2,
+ YM2203_LUMPED=0;
+parameter mask_div=1;
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;
@@ -103,7 +132,9 @@ wire [ 8:0] pcm;
// Test
wire pg_stop, eg_stop;
-wire ch6op;
+wire ch6op;
+wire [ 2:0] cur_ch;
+wire [ 1:0] cur_op;
// Operator
wire xuse_internal, yuse_internal;
@@ -118,19 +149,171 @@ wire lfo_rst;
wire [3:0] psg_addr;
wire [7:0] psg_data, psg_dout;
wire psg_wr_n;
+// ADPCM-A
+wire [15:0] addr_a;
+wire [ 2:0] up_addr, up_lracl;
+wire up_start, up_end;
+wire [ 7:0] aon_a, lracl;
+wire [ 5:0] atl_a; // ADPCM Total Level
+wire up_aon;
+// APDCM-B
+wire acmd_on_b; // Control - Process start, Key On
+wire acmd_rep_b; // Control - Repeat
+wire acmd_rst_b; // Control - Reset
+wire acmd_up_b; // Control - New cmd received
+wire [ 1:0] alr_b; // Left / Right
+wire [15:0] astart_b; // Start address
+wire [15:0] aend_b; // End address
+wire [15:0] adeltan_b; // Delta-N
+wire [ 7:0] aeg_b; // Envelope Generator Control
+wire [ 5:0] adpcma_flags; // ADPMC-A read over flags
+wire adpcmb_flag;
+wire [ 6:0] flag_ctl;
+wire [ 6:0] flag_mask;
+wire [ 1:0] div_setting;
-jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm))
+wire clk_en_2, clk_en_666, clk_en_111, clk_en_55;
+
+assign debug_view = { 4'd0, flag_B, flag_A, div_setting };
+
+generate
+if( use_adpcm==1 ) begin: gen_adpcm
+ wire rst_n;
+
+ jt12_rst u_rst(
+ .rst ( rst ),
+ .clk ( clk ),
+ .rst_n ( rst_n )
+ );
+
+ jt10_adpcm_drvA u_adpcm_a(
+ .rst_n ( rst_n ),
+ .clk ( clk ),
+ .cen ( cen ),
+ .cen6 ( clk_en_666 ), // clk & cen must be 666 kHz
+ .cen1 ( clk_en_111 ), // clk & cen must be 111 kHz
+
+ .addr ( adpcma_addr ), // real hardware has 10 pins multiplexed through RMPX pin
+ .bank ( adpcma_bank ),
+ .roe_n ( adpcma_roe_n ), // ADPCM-A ROM output enable
+ .datain ( adpcma_data ),
+
+ // Control Registers
+ .atl ( atl_a ), // ADPCM Total Level
+ .addr_in ( addr_a ),
+ .lracl_in ( lracl ),
+ .up_start ( up_start ),
+ .up_end ( up_end ),
+ .up_addr ( up_addr ),
+ .up_lracl ( up_lracl ),
+
+ .aon_cmd ( aon_a ), // ADPCM ON equivalent to key on for FM
+ .up_aon ( up_aon ),
+ // Flags
+ .flags ( adpcma_flags ),
+ .clr_flags ( flag_ctl[5:0] ),
+
+ .pcm55_l ( adpcmA_l ),
+ .pcm55_r ( adpcmA_r ),
+ .ch_enable ( ch_enable )
+ );
+
+ jt10_adpcm_drvB u_adpcm_b(
+ .rst_n ( rst_n ),
+ .clk ( clk ),
+ .cen ( cen ),
+ .cen55 ( clk_en_55 ),
+
+ // Control
+ .acmd_on_b ( acmd_on_b ), // Control - Process start, Key On
+ .acmd_rep_b ( acmd_rep_b ), // Control - Repeat
+ .acmd_rst_b ( acmd_rst_b ), // Control - Reset
+ .acmd_up_b ( acmd_up_b ), // Control - New command received
+ .alr_b ( alr_b ), // Left / Right
+ .astart_b ( astart_b ), // Start address
+ .aend_b ( aend_b ), // End address
+ .adeltan_b ( adeltan_b ), // Delta-N
+ .aeg_b ( aeg_b ), // Envelope Generator Control
+ // Flag
+ .flag ( adpcmb_flag ),
+ .clr_flag ( flag_ctl[6] ),
+ // memory
+ .addr ( adpcmb_addr ),
+ .data ( adpcmb_data ),
+ .roe_n ( adpcmb_roe_n ),
+
+ .pcm55_l ( adpcmB_l ),
+ .pcm55_r ( adpcmB_r )
+ );
+
+ assign snd_sample = zero;
+ jt10_acc u_acc(
+ .clk ( clk ),
+ .clk_en ( clk_en ),
+ .op_result ( op_result_hd ),
+ .rl ( rl ),
+ .zero ( zero ),
+ .s1_enters ( s2_enters ),
+ .s2_enters ( s1_enters ),
+ .s3_enters ( s4_enters ),
+ .s4_enters ( s3_enters ),
+ .cur_ch ( cur_ch ),
+ .cur_op ( cur_op ),
+ .alg ( alg_I ),
+ .adpcmA_l ( adpcmA_l ),
+ .adpcmA_r ( adpcmA_r ),
+ .adpcmB_l ( adpcmB_l ),
+ .adpcmB_r ( adpcmB_r ),
+ // combined output
+ .left ( fm_snd_left ),
+ .right ( fm_snd_right )
+ );
+end else begin : gen_adpcm_no
+ assign adpcmA_l = 'd0;
+ assign adpcmA_r = 'd0;
+ assign adpcmB_l = 'd0;
+ assign adpcmB_r = 'd0;
+ assign adpcma_addr = 'd0;
+ assign adpcma_bank = 'd0;
+ assign adpcma_roe_n = 'b1;
+ assign adpcmb_addr = 'd0;
+ assign adpcmb_roe_n = 'd1;
+ assign adpcma_flags = 0;
+ assign adpcmb_flag = 0;
+end
+endgenerate
+
+jt12_dout #(.use_ssg(use_ssg),.use_adpcm(use_adpcm)) u_dout(
+// .rst_n ( rst_n ),
+ .clk ( clk ), // CPU clock
+ .flag_A ( flag_A ),
+ .flag_B ( flag_B ),
+ .busy ( busy ),
+ .adpcma_flags ( adpcma_flags & flag_mask[5:0] ),
+ .adpcmb_flag ( adpcmb_flag & flag_mask[6] ),
+ .psg_dout ( psg_dout ),
+ .addr ( addr ),
+ .dout ( dout )
+);
+
+jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm), .use_adpcm(use_adpcm), .mask_div(mask_div))
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
+ .clk_en ( clk_en ), // internal clock enable
+ .clk_en_2 ( clk_en_2 ), // input cen divided by 2
+ .clk_en_ssg ( clk_en_ssg), // internal clock enable
+ .clk_en_666 ( clk_en_666),
+ .clk_en_111 ( clk_en_111),
+ .clk_en_55 ( clk_en_55 ),
.din ( din ),
.write ( write ),
.addr ( addr ),
.busy ( busy ),
.ch6op ( ch6op ),
+ .cur_ch ( cur_ch ),
+ .cur_op ( cur_op ),
// LFO
.lfo_freq ( lfo_freq ),
.lfo_en ( lfo_en ),
@@ -150,11 +333,32 @@ jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm))
.pcm ( pcm ),
.pcm_en ( pcm_en ),
.pcm_wr ( pcm_wr ),
-
+ // ADPCM-A
+ .aon_a ( aon_a ), // ON
+ .atl_a ( atl_a ), // TL
+ .addr_a ( addr_a ), // address latch
+ .lracl ( lracl ), // L/R ADPCM Channel Level
+ .up_start ( up_start ), // write enable start address latch
+ .up_end ( up_end ), // write enable end address latch
+ .up_addr ( up_addr ), // write enable end address latch
+ .up_lracl ( up_lracl ),
+ .up_aon ( up_aon ),
+ // ADPCM-B
+ .acmd_on_b ( acmd_on_b ), // Control - Process start, Key On
+ .acmd_rep_b ( acmd_rep_b ), // Control - Repeat
+ .acmd_rst_b ( acmd_rst_b ), // Control - Reset
+ .acmd_up_b ( acmd_up_b ), // Control - New command received
+ .alr_b ( alr_b ), // Left / Right
+ .astart_b ( astart_b ), // Start address
+ .aend_b ( aend_b ), // End address
+ .adeltan_b ( adeltan_b ), // Delta-N
+ .aeg_b ( aeg_b ), // Envelope Generator Control
+ .flag_ctl ( flag_ctl ),
+ .flag_mask ( flag_mask ),
// Operator
.xuse_prevprev1 ( xuse_prevprev1 ),
.xuse_internal ( xuse_internal ),
- .yuse_internal ( yuse_internal ),
+ .yuse_internal ( yuse_internal ),
.xuse_prev2 ( xuse_prev2 ),
.yuse_prev1 ( yuse_prev1 ),
.yuse_prev2 ( yuse_prev2 ),
@@ -180,7 +384,7 @@ jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm))
.sl_I ( sl_I ),
.ks_II ( ks_II ),
- .eg_stop ( eg_stop ),
+ .eg_stop ( eg_stop ),
// SSG operation
.ssg_en_I ( ssg_en_I ),
.ssg_eg_I ( ssg_eg_I ),
@@ -195,19 +399,25 @@ jt12_mmr #(.use_ssg(use_ssg),.num_ch(num_ch),.use_pcm(use_pcm))
// PSG interace
.psg_addr ( psg_addr ),
.psg_data ( psg_data ),
- .psg_wr_n ( psg_wr_n )
+ .psg_wr_n ( psg_wr_n ),
+ .debug_bus ( debug_bus ),
+ .div_setting(div_setting)
);
-jt12_timers u_timers(
+// YM2203 seems to use a fixed cen/3 clock for the timers, regardless
+// of the prescaler setting
+wire timer_cen = fast_timers ? cen : clk_en;
+jt12_timers #(.num_ch(num_ch)) u_timers (
.clk ( clk ),
- .clk_en ( clk_en | fast_timers ),
+ .clk_en ( timer_cen ),
.rst ( rst ),
+ .zero ( zero ),
.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 ),
+ .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 ),
@@ -218,7 +428,7 @@ jt12_timers u_timers(
// YM2203 does not have LFO
generate
-if( use_lfo== 1)
+if( use_lfo== 1) begin : gen_lfo
jt12_lfo u_lfo(
.rst ( rst ),
.clk ( clk ),
@@ -233,43 +443,66 @@ if( use_lfo== 1)
.lfo_freq ( lfo_freq ),
.lfo_mod ( lfo_mod )
);
-else
+end else begin : gen_nolfo
assign lfo_mod = 7'd0;
+end
endgenerate
// YM2203/YM2610 have a PSG
+`ifndef NOSSG
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)
+ if( use_ssg==1 ) begin : gen_ssg
+ jt49 #(.COMP(3'b01), .CLKDIV(JT49_DIV), .YM2203_LUMPED(YM2203_LUMPED))
+ u_psg( // note that input ports are not multiplexed
+ .rst_n ( ~rst ),
+ .clk ( clk ), // signal on positive edge
+ .clk_en ( clk_en_ssg), // clock enable on negative edge
+ .addr ( psg_addr ),
+ .cs_n ( 1'b0 ),
+ .wr_n ( psg_wr_n ), // write
+ .din ( psg_data ),
+ .sound ( psg_snd ), // combined output
+ .A ( psg_A ),
+ .B ( psg_B ),
+ .C ( psg_C ),
+ .dout ( psg_dout ),
+ .sel ( 1'b1 ), // half clock speed
+ .IOA_out ( IOA_out ),
+ .IOB_out ( IOB_out ),
+ .IOA_in ( IOA_in ),
+ .IOB_in ( IOB_in ),
+ .IOA_oe ( IOA_oe ),
+ .IOB_oe ( IOB_oe ),
+ // Unused:
+ .sample ( )
);
- 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 snd_left = fm_snd_left + { 1'b0, psg_snd[9:0],5'd0};
+ assign snd_right = fm_snd_right + { 1'b0, psg_snd[9:0],5'd0};
+ end else begin : gen_nossg
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;
+ assign psg_A = 8'd0;
+ assign psg_B = 8'd0;
+ assign psg_C = 8'd0;
+ assign IOA_oe = 0;
+ assign IOB_oe = 0;
+ assign IOA_out = 0;
+ assign IOB_out = 0;
end
endgenerate
+`else
+ assign psg_snd = 10'd0;
+ assign snd_left = fm_snd_left;
+ assign snd_right= fm_snd_right;
+ assign psg_dout = 8'd0;
+`endif
-
-`ifndef TIMERONLY
+wire [ 8:0] op_result;
+wire [13:0] op_result_hd;
+`ifndef NOFM
jt12_pg #(.num_ch(num_ch)) u_pg(
.rst ( rst ),
@@ -299,7 +532,7 @@ jt12_eg #(.num_ch(num_ch)) u_eg(
.clk ( clk ),
.clk_en ( clk_en ),
.zero ( zero ),
- .eg_stop ( eg_stop ),
+ .eg_stop ( eg_stop ),
// envelope configuration
.keycode_II ( keycode_II ),
.arate_I ( ar_I ), // attack rate
@@ -330,9 +563,6 @@ jt12_sh #(.width(10),.stages(4)) u_egpad(
.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 ),
@@ -348,25 +578,30 @@ jt12_op #(.num_ch(num_ch)) u_op(
.s4_enters ( s4_enters ),
.xuse_prevprev1 ( xuse_prevprev1),
.xuse_internal ( xuse_internal ),
- .yuse_internal ( yuse_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 )
+ .full_result ( op_result_hd )
);
+`else
+assign op_result = 'd0;
+assign op_result_hd = 'd0;
+`endif
generate
- if( use_lr==1 ) begin
+ if( use_pcm==1 ) begin: gen_pcm_acc // YM2612 accumulator
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;
+ reg 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 ),
@@ -376,14 +611,40 @@ generate
.pcm_wr ( pcm_wr ),
.pcm_resampled ( pcm2 )
);
+ */
+ wire rst_pcm_n;
- jt12_acc #(.num_ch(num_ch)) u_acc(
+ jt12_rst u_rst_pcm(
+ .rst ( rst ),
+ .clk ( clk ),
+ .rst_n ( rst_pcm_n )
+ );
+
+ `ifndef NOPCMLINEAR
+ wire signed [10:0] pcm_full;
+ always @(*)
+ pcm2 = en_hifi_pcm ? pcm_full[9:1] : pcm;
+
+ jt12_pcm_interpol #(.DW(11), .stepw(5)) u_pcm (
+ .rst_n ( rst_pcm_n ),
+ .clk ( clk ),
+ .cen ( clk_en ),
+ .cen55 ( clk_en_55 ),
+ .pcm_wr( pcm_wr ),
+ .pcmin ( {pcm[8],pcm, 1'b0} ),
+ .pcmout( pcm_full )
+ );
+ `else
+ assign pcm2 = pcm;
+ `endif
+
+ jt12_acc u_acc(
.rst ( rst ),
.clk ( clk ),
.clk_en ( clk_en ),
.op_result ( op_result ),
.rl ( rl ),
- // note that the order changes to deal
+ // note that the order changes to deal
// with the operator pipeline delay
.zero ( zero ),
.s1_enters ( s2_enters ),
@@ -398,7 +659,8 @@ generate
.left ( fm_snd_left [15:4] ),
.right ( fm_snd_right[15:4] )
);
- end else begin
+ end
+ if( use_pcm==0 && use_adpcm==0 ) begin : gen_2203_acc // YM2203 accumulator
wire signed [15:0] mono_snd;
assign fm_snd_left = mono_snd;
assign fm_snd_right = mono_snd;
@@ -407,8 +669,8 @@ generate
.rst ( rst ),
.clk ( clk ),
.clk_en ( clk_en ),
- .op_result ( full_result ),
- // note that the order changes to deal
+ .op_result ( op_result_hd ),
+ // note that the order changes to deal
// with the operator pipeline delay
.s1_enters ( s1_enters ),
.s2_enters ( s2_enters ),
@@ -418,59 +680,18 @@ generate
.zero ( zero ),
// combined output
.snd ( mono_snd )
- );
- end
+ );
+ end
endgenerate
`ifdef SIMULATION
-/* verilator lint_off PINMISSING */
-reg [4:0] sep24_cnt;
+integer fsnd;
+initial begin
+ fsnd=$fopen("jt12.raw","wb");
+end
-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 */
+always @(posedge zero) begin
+ $fwrite(fsnd,"%u", {snd_left, snd_right});
+end
`endif
endmodule
diff --git a/rtl/sound/jt12/lfo_sh1_lut.hex b/rtl/sound/jt12/lfo_sh1_lut.hex
deleted file mode 100644
index 16afdfb..0000000
--- a/rtl/sound/jt12/lfo_sh1_lut.hex
+++ /dev/null
@@ -1,64 +0,0 @@
-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
\ No newline at end of file
diff --git a/rtl/sound/jt12/lfo_sh2_lut.hex b/rtl/sound/jt12/lfo_sh2_lut.hex
deleted file mode 100644
index 57c3527..0000000
--- a/rtl/sound/jt12/lfo_sh2_lut.hex
+++ /dev/null
@@ -1,64 +0,0 @@
-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
\ No newline at end of file
diff --git a/rtl/sound/jt49/jt49.qip b/rtl/sound/jt49/jt49.qip
new file mode 100644
index 0000000..6568ae9
--- /dev/null
+++ b/rtl/sound/jt49/jt49.qip
@@ -0,0 +1,7 @@
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_bus.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_div.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_cen.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_eg.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_exp.v ]
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_noise.v ]
diff --git a/rtl/sound/jt49/jt49.v b/rtl/sound/jt49/jt49.v
new file mode 100644
index 0000000..08145bf
--- /dev/null
+++ b/rtl/sound/jt49/jt49.v
@@ -0,0 +1,258 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 10-Nov-2018
+
+ Based on sqmusic, by the same author
+
+ */
+
+module jt49 ( // note that input ports are not multiplexed
+ input rst_n,
+ input clk, // signal on positive edge
+ input clk_en /* synthesis direct_enable = 1 */,
+ input [3:0] addr,
+ input cs_n,
+ input wr_n, // write
+ input [7:0] din,
+ input sel, // if sel is low, the clock is divided by 2
+ output reg [7:0] dout,
+ output reg [9:0] sound, // combined channel output
+ output reg [7:0] A, // linearised channel output
+ output reg [7:0] B,
+ output reg [7:0] C,
+ output sample,
+
+ input [7:0] IOA_in,
+ output [7:0] IOA_out,
+ output IOA_oe,
+
+ input [7:0] IOB_in,
+ output [7:0] IOB_out,
+ output IOB_oe
+);
+
+parameter [2:0] COMP=3'b000;
+parameter YM2203_LUMPED=0;
+parameter CLKDIV=3;
+wire [2:0] comp = COMP;
+
+reg [7:0] regarray[15:0];
+wire [7:0] port_A, port_B;
+
+wire [4:0] envelope;
+wire bitA, bitB, bitC;
+wire noise;
+reg Amix, Bmix, Cmix;
+
+wire cen16, cen256;
+
+assign IOA_out = regarray[14];
+assign IOB_out = regarray[15];
+assign port_A = IOA_in;
+assign port_B = IOB_in;
+assign IOA_oe = regarray[7][6];
+assign IOB_oe = regarray[7][7];
+assign sample = cen16;
+
+jt49_cen #(.CLKDIV(CLKDIV)) u_cen(
+ .clk ( clk ),
+ .rst_n ( rst_n ),
+ .cen ( clk_en ),
+ .sel ( sel ),
+ .cen16 ( cen16 ),
+ .cen256 ( cen256 )
+);
+
+// internal modules operate at clk/16
+jt49_div #(12) u_chA(
+ .clk ( clk ),
+ .rst_n ( rst_n ),
+ .cen ( cen16 ),
+ .period ( {regarray[1][3:0], regarray[0][7:0] } ),
+ .div ( bitA )
+);
+
+jt49_div #(12) u_chB(
+ .clk ( clk ),
+ .rst_n ( rst_n ),
+ .cen ( cen16 ),
+ .period ( {regarray[3][3:0], regarray[2][7:0] } ),
+ .div ( bitB )
+);
+
+jt49_div #(12) u_chC(
+ .clk ( clk ),
+ .rst_n ( rst_n ),
+ .cen ( cen16 ),
+ .period ( {regarray[5][3:0], regarray[4][7:0] } ),
+ .div ( bitC )
+);
+
+jt49_noise u_ng(
+ .clk ( clk ),
+ .cen ( cen16 ),
+ .rst_n ( rst_n ),
+ .period ( regarray[6][4:0] ),
+ .noise ( noise )
+);
+
+// envelope generator
+wire eg_step;
+wire [15:0] eg_period = {regarray[4'hc],regarray[4'hb]};
+wire null_period = eg_period == 16'h0;
+
+jt49_div #(16) u_envdiv(
+ .clk ( clk ),
+ .cen ( cen256 ),
+ .rst_n ( rst_n ),
+ .period ( eg_period ),
+ .div ( eg_step )
+);
+
+reg eg_restart;
+
+jt49_eg u_env(
+ .clk ( clk ),
+ .cen ( cen256 ),
+ .step ( eg_step ),
+ .rst_n ( rst_n ),
+ .restart ( eg_restart ),
+ .null_period( null_period ),
+ .ctrl ( regarray[4'hD][3:0] ),
+ .env ( envelope )
+);
+
+reg [4:0] logA, logB, logC, log;
+wire [7:0] lin;
+
+jt49_exp u_exp(
+ .clk ( clk ),
+ .comp ( comp ),
+ .din ( log ),
+ .dout ( lin )
+);
+
+wire [4:0] volA = { regarray[ 8][3:0], regarray[ 8][3] };
+wire [4:0] volB = { regarray[ 9][3:0], regarray[ 9][3] };
+wire [4:0] volC = { regarray[10][3:0], regarray[10][3] };
+wire use_envA = regarray[ 8][4];
+wire use_envB = regarray[ 9][4];
+wire use_envC = regarray[10][4];
+wire use_noA = regarray[ 7][3];
+wire use_noB = regarray[ 7][4];
+wire use_noC = regarray[ 7][5];
+
+reg [3:0] acc_st;
+
+always @(posedge clk) if( clk_en ) begin
+ Amix <= (noise|use_noA) & (bitA|regarray[7][0]);
+ Bmix <= (noise|use_noB) & (bitB|regarray[7][1]);
+ Cmix <= (noise|use_noC) & (bitC|regarray[7][2]);
+
+ logA <= !Amix ? 5'd0 : (use_envA ? envelope : volA );
+ logB <= !Bmix ? 5'd0 : (use_envB ? envelope : volB );
+ logC <= !Cmix ? 5'd0 : (use_envC ? envelope : volC );
+end
+
+reg [9:0] acc;
+wire [9:0] elin;
+
+assign elin = {2'd0,lin};
+
+always @(posedge clk, negedge rst_n) begin
+ if( !rst_n ) begin
+ acc_st <= 4'b1;
+ acc <= 10'd0;
+ A <= 8'd0;
+ B <= 8'd0;
+ C <= 8'd0;
+ sound <= 10'd0;
+ end else if(clk_en) begin
+ acc_st <= { acc_st[2:0], acc_st[3] };
+ // Lumping the channel outputs for YM2203 will cause only the higher
+ // voltage to pass throuh, as the outputs seem to use a source follower.
+ acc <= YM2203_LUMPED==1 ? (acc>elin ? acc : elin) : acc + elin;
+ case( acc_st )
+ 4'b0001: begin
+ log <= logA;
+ acc <= 10'd0;
+ sound <= acc;
+ end
+ 4'b0010: begin
+ A <= lin;
+ log <= logB;
+ end
+ 4'b0100: begin
+ B <= lin;
+ log <= logC;
+ end
+ 4'b1000: begin // last sum
+ C <= lin;
+ end
+ default:;
+ endcase
+ end
+end
+
+reg [7:0] read_mask;
+
+always @(*)
+ case(addr)
+ 4'h0,4'h2,4'h4,4'h7,4'hb,4'hc,4'he,4'hf:
+ read_mask = 8'hff;
+ 4'h1,4'h3,4'h5,4'hd:
+ read_mask = 8'h0f;
+ 4'h6,4'h8,4'h9,4'ha:
+ read_mask = 8'h1f;
+ endcase // addr
+
+// register array
+wire write;
+reg last_write;
+wire wr_edge = write & ~last_write;
+
+assign write = !wr_n && !cs_n;
+
+always @(posedge clk, negedge rst_n) begin
+ if( !rst_n ) begin
+ dout <= 8'd0;
+ last_write <= 0;
+ eg_restart <= 0;
+ regarray[0]<=8'd0; regarray[4]<=8'd0; regarray[ 8]<=8'd0; regarray[12]<=8'd0;
+ regarray[1]<=8'd0; regarray[5]<=8'd0; regarray[ 9]<=8'd0; regarray[13]<=8'd0;
+ regarray[2]<=8'd0; regarray[6]<=8'd0; regarray[10]<=8'd0; regarray[14]<=8'd0;
+ regarray[3]<=8'd0; regarray[7]<=8'd0; regarray[11]<=8'd0; regarray[15]<=8'd0;
+ end else begin
+ last_write <= write;
+ // Data read
+ case( addr )
+ 4'he: dout <= port_A;
+ 4'hf: dout <= port_B;
+ default: dout <= regarray[ addr ] & read_mask;
+ endcase
+ // Data write
+ if( write ) begin
+ regarray[addr] <= din;
+ if ( addr == 4'hD && wr_edge ) eg_restart <= 1;
+ end else begin
+ eg_restart <= 0;
+ end
+ end
+end
+
+endmodule
diff --git a/rtl/sound/jt49/jt49_bus.v b/rtl/sound/jt49/jt49_bus.v
new file mode 100644
index 0000000..ac48e8e
--- /dev/null
+++ b/rtl/sound/jt49/jt49_bus.v
@@ -0,0 +1,105 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 28-Jan-2019
+
+ Based on sqmusic, by the same author
+
+ */
+
+// This is a wrapper with the BDIR/BC1 pins
+
+module jt49_bus ( // note that input ports are not multiplexed
+ input rst_n,
+ input clk, // signal on positive edge
+ input clk_en /* synthesis direct_enable = 1 */,
+ // bus control pins of original chip
+ input bdir,
+ input bc1,
+ input [7:0] din,
+
+ input sel, // if sel is low, the clock is divided by 2
+ output [7:0] dout,
+ output [9:0] sound, // combined channel output
+ output [7:0] A, // linearised channel output
+ output [7:0] B,
+ output [7:0] C,
+ output sample,
+
+ input [7:0] IOA_in,
+ output [7:0] IOA_out,
+ output IOA_oe,
+
+ input [7:0] IOB_in,
+ output [7:0] IOB_out,
+ output IOB_oe
+);
+
+parameter [2:0] COMP=3'b000;
+
+reg wr_n, cs_n;
+reg [3:0] addr;
+reg addr_ok;
+reg [7:0] din_latch;
+
+always @(posedge clk)
+ if( !rst_n ) begin
+ wr_n <= 1'b1;
+ cs_n <= 1'b1;
+ addr <= 4'd0;
+ addr_ok <= 1'b1;
+ end else begin // I/O cannot use clk_en
+ // addr must be
+ case( {bdir,bc1} )
+ 2'b00: { wr_n, cs_n } <= 2'b11;
+ 2'b01: { wr_n, cs_n } <= addr_ok ? 2'b10 : 2'b11;
+ 2'b10: begin
+ { wr_n, cs_n } <= addr_ok ? 2'b00 : 2'b11;
+ din_latch <= din;
+ end
+ 2'b11: begin
+ { wr_n, cs_n } <= 2'b11;
+ addr <= din[3:0];
+ addr_ok <= din[7:4] == 4'd0;
+ end
+ endcase // {bdir,bc1}
+ end
+
+jt49 #(.COMP(COMP)) u_jt49( // note that input ports are not multiplexed
+ .rst_n ( rst_n ),
+ .clk ( clk ), // signal on positive edge
+ .clk_en ( clk_en ), // clock enable on negative edge
+ .addr ( addr[3:0] ),
+ .cs_n ( cs_n ),
+ .wr_n ( wr_n ), // write
+ .din ( din_latch ),
+ .sel ( sel ), // if sel is low, the clock is divided by 2
+ .dout ( dout ),
+ .sound ( sound ), // combined channel output
+ .sample ( sample ),
+ .A ( A ), // linearised channel output
+ .B ( B ),
+ .C ( C ),
+ .IOA_in ( IOA_in ),
+ .IOA_out( IOA_out ),
+ .IOA_oe ( IOA_oe ),
+ .IOB_in ( IOB_in ),
+ .IOB_out( IOB_out ),
+ .IOB_oe ( IOB_oe )
+);
+
+endmodule // jt49_bus
\ No newline at end of file
diff --git a/rtl/sound/jt49/jt49_cen.v b/rtl/sound/jt49/jt49_cen.v
new file mode 100644
index 0000000..671eceb
--- /dev/null
+++ b/rtl/sound/jt49/jt49_cen.v
@@ -0,0 +1,55 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 10-Nov-2018
+
+ Based on sqmusic, by the same author
+
+ */
+
+module jt49_cen(
+ input clk,
+ input rst_n,
+ input cen, // base clock enable signal
+ input sel, // when low, divide by 2 once more
+ output reg cen16,
+ output reg cen256
+);
+
+reg [9:0] cencnt;
+parameter CLKDIV = 3; // use 3 for standalone JT49 or 2
+localparam eg = CLKDIV; //8;
+
+wire toggle16 = sel ? ~|cencnt[CLKDIV-1:0] : ~|cencnt[CLKDIV:0];
+wire toggle256= sel ? ~|cencnt[eg-2:0] : ~|cencnt[eg-1:0];
+
+
+always @(posedge clk, negedge rst_n) begin
+ if(!rst_n)
+ cencnt <= 10'd0;
+ else begin
+ if(cen) cencnt <= cencnt+10'd1;
+ end
+end
+
+always @(posedge clk) begin
+ cen16 <= cen & toggle16;
+ cen256 <= cen & toggle256;
+end
+
+
+endmodule // jt49_cen
diff --git a/rtl/sound/jt49/jt49_div.v b/rtl/sound/jt49/jt49_div.v
new file mode 100644
index 0000000..ac4564c
--- /dev/null
+++ b/rtl/sound/jt49/jt49_div.v
@@ -0,0 +1,52 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 10-Nov-2018
+
+ Based on sqmusic, by the same author
+
+ */
+
+
+module jt49_div #(parameter W=12 )(
+ (* direct_enable *) input cen,
+ input clk, // this is the divided down clock from the core
+ input rst_n,
+ input [W-1:0] period,
+ output reg div
+);
+
+reg [W-1:0]count;
+
+wire [W-1:0] one = { {W-1{1'b0}}, 1'b1};
+
+always @(posedge clk, negedge rst_n ) begin
+ if( !rst_n) begin
+ count <= one;
+ div <= 1'b0;
+ end
+ else if(cen) begin
+ if( count>=period ) begin
+ count <= one;
+ div <= ~div;
+ end
+ else
+ /*if( period!={W{1'b0}} )*/ count <= count + one ;
+ end
+end
+
+endmodule
diff --git a/rtl/sound/jt49/jt49_eg.v b/rtl/sound/jt49/jt49_eg.v
new file mode 100644
index 0000000..46dd62a
--- /dev/null
+++ b/rtl/sound/jt49/jt49_eg.v
@@ -0,0 +1,88 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 10-Nov-2018
+
+ Based on sqmusic, by the same author
+
+ */
+
+module jt49_eg(
+ (* direct_enable *) input cen,
+ input clk, // this is the divided down clock from the core
+ input step,
+ input null_period,
+ input rst_n,
+ input restart,
+ input [3:0] ctrl,
+ output reg [4:0]env
+);
+
+reg inv, stop;
+reg [4:0] gain;
+
+wire CONT = ctrl[3];
+wire ATT = ctrl[2];
+wire ALT = ctrl[1];
+wire HOLD = ctrl[0];
+
+wire will_hold = !CONT || HOLD;
+
+always @(posedge clk)
+ if( cen ) env <= inv ? ~gain : gain;
+
+reg last_step;
+wire step_edge = (step && !last_step) || null_period;
+wire will_invert = (!CONT&&ATT) || (CONT&&ALT);
+reg rst_latch, rst_clr;
+
+always @(posedge clk) begin
+ if( restart ) rst_latch <= 1;
+ else if(rst_clr ) rst_latch <= 0;
+end
+
+always @( posedge clk, negedge rst_n )
+ if( !rst_n) begin
+ gain <= 5'h1F;
+ inv <= 0;
+ stop <= 0;
+ rst_clr <= 0;
+ end
+ else if( cen ) begin
+ last_step <= step;
+ if( rst_latch ) begin
+ gain <= 5'h1F;
+ inv <= ATT;
+ stop <= 1'b0;
+ rst_clr <= 1;
+ end
+ else begin
+ rst_clr <= 0;
+ if (step_edge && !stop) begin
+ if( gain==5'h00 ) begin
+ if( will_hold )
+ stop <= 1'b1;
+ else
+ gain <= gain-5'b1;
+ if( will_invert ) inv<=~inv;
+ end
+ else gain <= gain-5'b1;
+ end
+ end
+ end
+
+endmodule
diff --git a/rtl/sound/jt49/jt49_exp.v b/rtl/sound/jt49/jt49_exp.v
new file mode 100644
index 0000000..25efa38
--- /dev/null
+++ b/rtl/sound/jt49/jt49_exp.v
@@ -0,0 +1,205 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 10-Nov-2018
+
+ Based on sqmusic, by the same author
+
+ */
+
+// Compression vs dynamic range
+// 0 -> 43.6dB
+// 1 -> 29.1
+// 2 -> 21.8
+// 3 -> 13.4
+
+module jt49_exp(
+ input clk,
+ input [2:0] comp, // compression
+ input [4:0] din,
+ output reg [7:0] dout
+);
+
+reg [7:0] lut[0:159];
+
+always @(posedge clk)
+ dout <= lut[ {comp,din} ];
+
+initial begin
+ lut[0] = 8'd0;
+ lut[1] = 8'd1;
+ lut[2] = 8'd1;
+ lut[3] = 8'd1;
+ lut[4] = 8'd2;
+ lut[5] = 8'd2;
+ lut[6] = 8'd3;
+ lut[7] = 8'd3;
+ lut[8] = 8'd4;
+ lut[9] = 8'd5;
+ lut[10] = 8'd6;
+ lut[11] = 8'd7;
+ lut[12] = 8'd9;
+ lut[13] = 8'd11;
+ lut[14] = 8'd13;
+ lut[15] = 8'd15;
+ lut[16] = 8'd18;
+ lut[17] = 8'd22;
+ lut[18] = 8'd26;
+ lut[19] = 8'd31;
+ lut[20] = 8'd37;
+ lut[21] = 8'd45;
+ lut[22] = 8'd53;
+ lut[23] = 8'd63;
+ lut[24] = 8'd75;
+ lut[25] = 8'd90;
+ lut[26] = 8'd107;
+ lut[27] = 8'd127;
+ lut[28] = 8'd151;
+ lut[29] = 8'd180;
+ lut[30] = 8'd214;
+ lut[31] = 8'd255;
+ lut[32] = 8'd0;
+ lut[33] = 8'd7;
+ lut[34] = 8'd8;
+ lut[35] = 8'd10;
+ lut[36] = 8'd11;
+ lut[37] = 8'd12;
+ lut[38] = 8'd14;
+ lut[39] = 8'd15;
+ lut[40] = 8'd17;
+ lut[41] = 8'd20;
+ lut[42] = 8'd22;
+ lut[43] = 8'd25;
+ lut[44] = 8'd28;
+ lut[45] = 8'd31;
+ lut[46] = 8'd35;
+ lut[47] = 8'd40;
+ lut[48] = 8'd45;
+ lut[49] = 8'd50;
+ lut[50] = 8'd56;
+ lut[51] = 8'd63;
+ lut[52] = 8'd71;
+ lut[53] = 8'd80;
+ lut[54] = 8'd90;
+ lut[55] = 8'd101;
+ lut[56] = 8'd113;
+ lut[57] = 8'd127;
+ lut[58] = 8'd143;
+ lut[59] = 8'd160;
+ lut[60] = 8'd180;
+ lut[61] = 8'd202;
+ lut[62] = 8'd227;
+ lut[63] = 8'd255;
+ lut[64] = 8'd0;
+ lut[65] = 8'd18;
+ lut[66] = 8'd20;
+ lut[67] = 8'd22;
+ lut[68] = 8'd24;
+ lut[69] = 8'd26;
+ lut[70] = 8'd29;
+ lut[71] = 8'd31;
+ lut[72] = 8'd34;
+ lut[73] = 8'd37;
+ lut[74] = 8'd41;
+ lut[75] = 8'd45;
+ lut[76] = 8'd49;
+ lut[77] = 8'd53;
+ lut[78] = 8'd58;
+ lut[79] = 8'd63;
+ lut[80] = 8'd69;
+ lut[81] = 8'd75;
+ lut[82] = 8'd82;
+ lut[83] = 8'd90;
+ lut[84] = 8'd98;
+ lut[85] = 8'd107;
+ lut[86] = 8'd116;
+ lut[87] = 8'd127;
+ lut[88] = 8'd139;
+ lut[89] = 8'd151;
+ lut[90] = 8'd165;
+ lut[91] = 8'd180;
+ lut[92] = 8'd196;
+ lut[93] = 8'd214;
+ lut[94] = 8'd233;
+ lut[95] = 8'd255;
+ lut[96] = 8'd0;
+ lut[97] = 8'd51;
+ lut[98] = 8'd54;
+ lut[99] = 8'd57;
+ lut[100] = 8'd60;
+ lut[101] = 8'd63;
+ lut[102] = 8'd67;
+ lut[103] = 8'd70;
+ lut[104] = 8'd74;
+ lut[105] = 8'd78;
+ lut[106] = 8'd83;
+ lut[107] = 8'd87;
+ lut[108] = 8'd92;
+ lut[109] = 8'd97;
+ lut[110] = 8'd103;
+ lut[111] = 8'd108;
+ lut[112] = 8'd114;
+ lut[113] = 8'd120;
+ lut[114] = 8'd127;
+ lut[115] = 8'd134;
+ lut[116] = 8'd141;
+ lut[117] = 8'd149;
+ lut[118] = 8'd157;
+ lut[119] = 8'd166;
+ lut[120] = 8'd175;
+ lut[121] = 8'd185;
+ lut[122] = 8'd195;
+ lut[123] = 8'd206;
+ lut[124] = 8'd217;
+ lut[125] = 8'd229;
+ lut[126] = 8'd241;
+ lut[127] = 8'd255;
+ lut[128] = 8'd0;
+ lut[129] = 8'd8;
+ lut[130] = 8'd10;
+ lut[131] = 8'd12;
+ lut[132] = 8'd16;
+ lut[133] = 8'd22;
+ lut[134] = 8'd29;
+ lut[135] = 8'd35;
+ lut[136] = 8'd44;
+ lut[137] = 8'd50;
+ lut[138] = 8'd56;
+ lut[139] = 8'd60;
+ lut[140] = 8'd64;
+ lut[141] = 8'd85;
+ lut[142] = 8'd97;
+ lut[143] = 8'd103;
+ lut[144] = 8'd108;
+ lut[145] = 8'd120;
+ lut[146] = 8'd127;
+ lut[147] = 8'd134;
+ lut[148] = 8'd141;
+ lut[149] = 8'd149;
+ lut[150] = 8'd157;
+ lut[151] = 8'd166;
+ lut[152] = 8'd175;
+ lut[153] = 8'd185;
+ lut[154] = 8'd195;
+ lut[155] = 8'd206;
+ lut[156] = 8'd217;
+ lut[157] = 8'd229;
+ lut[158] = 8'd241;
+ lut[159] = 8'd255;
+
+end
+endmodule
diff --git a/rtl/sound/jt49/jt49_noise.v b/rtl/sound/jt49/jt49_noise.v
new file mode 100644
index 0000000..ffc1fb9
--- /dev/null
+++ b/rtl/sound/jt49/jt49_noise.v
@@ -0,0 +1,62 @@
+/* This file is part of JT49.
+
+ JT49 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.
+
+ JT49 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 JT49. If not, see .
+
+ Author: Jose Tejada Gomez. Twitter: @topapate
+ Version: 1.0
+ Date: 10-Nov-2018
+
+ Based on sqmusic, by the same author
+
+ */
+
+
+module jt49_noise(
+ (* direct_enable *) input cen,
+ input clk,
+ input rst_n,
+ input [4:0] period,
+ output reg noise
+);
+
+reg [5:0]count;
+reg [16:0]poly17;
+wire poly17_zero = poly17==17'b0;
+wire noise_en;
+reg last_en;
+
+wire noise_up = noise_en && !last_en;
+
+always @(posedge clk ) if(cen) begin
+ noise <= ~poly17[0];
+end
+
+always @( posedge clk, negedge rst_n )
+ if( !rst_n )
+ poly17 <= 17'd0;
+ else if( cen ) begin
+ last_en <= noise_en;
+ if( noise_up )
+ poly17 <= { poly17[0] ^ poly17[3] ^ poly17_zero, poly17[16:1] };
+ end
+
+jt49_div #(5) u_div(
+ .clk ( clk ),
+ .cen ( cen ),
+ .rst_n ( rst_n ),
+ .period ( period ),
+ .div ( noise_en )
+);
+
+endmodule
\ No newline at end of file
diff --git a/rtl/sound/turbosound.sv b/rtl/sound/turbosound.sv
index 7a8e59c..dbb7616 100644
--- a/rtl/sound/turbosound.sv
+++ b/rtl/sound/turbosound.sv
@@ -32,7 +32,14 @@ module turbosound
output [7:0] DO, // Data Out
output [11:0] CHANNEL_L, // Output channel L
- output [11:0] CHANNEL_R // Output channel R
+ output [11:0] CHANNEL_R, // Output channel R
+
+ input [7:0] IOA_in,
+ input [7:0] IOB_in,
+ output [7:0] IOA_out,
+ output [7:0] IOB_out,
+ output IOA_oe,
+ output IOB_oe
);
@@ -145,7 +152,14 @@ jt03 ym2203_1
.psg_B(psg_ch_b_1),
.psg_C(psg_ch_c_1),
- .fm_snd(opn_1)
+ .fm_snd(opn_1),
+
+ .IOA_in(IOA_in),
+ .IOB_in(IOB_in),
+ .IOA_out(IOA_out),
+ .IOB_out(IOB_out),
+ .IOA_oe(IOA_oe),
+ .IOB_oe(IOB_oe)
);
assign DO = ay_select ? DO_1 : DO_0;
diff --git a/rtl/sound/ym2149.sv b/rtl/sound/ym2149.sv
deleted file mode 100644
index 672cbda..0000000
--- a/rtl/sound/ym2149.sv
+++ /dev/null
@@ -1,326 +0,0 @@
-//
-// Copyright (c) MikeJ - Jan 2005
-// Copyright (c) 2016-2019 Sorgelig
-//
-// All rights reserved
-//
-// Redistribution and use in source and synthezised forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// Redistributions in synthesized form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// Neither the name of the author nor the names of other contributors may
-// be used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-
-
-// BDIR BC MODE
-// 0 0 inactive
-// 0 1 read value
-// 1 0 write value
-// 1 1 set address
-//
-
-module ym2149
-(
- input CLK, // Global clock
- input CE, // PSG Clock enable
- input RESET, // Chip RESET (set all Registers to '0', active hi)
- input BDIR, // Bus Direction (0 - read , 1 - write)
- input BC, // Bus control
- 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
-
- input SEL,
- input MODE,
-
- output [5:0] ACTIVE,
-
- input [7:0] IOA_in,
- output [7:0] IOA_out,
-
- input [7:0] IOB_in,
- output [7:0] IOB_out
-);
-
-assign ACTIVE = ~ymreg[7][5:0];
-assign IOA_out = ymreg[14];
-assign IOB_out = ymreg[15];
-
-reg [7:0] addr;
-reg [7:0] ymreg[16];
-
-// Write to PSG
-reg env_reset;
-always @(posedge CLK) begin
- if(RESET) begin
- ymreg <= '{default:0};
- ymreg[7] <= '1;
- addr <= '0;
- env_reset <= 0;
- end else begin
- env_reset <= 0;
- if(BDIR) begin
- if(BC) addr <= DI;
- else if(!addr[7:4]) begin
- ymreg[addr[3:0]] <= DI;
- env_reset <= (addr == 13);
- end
- end
- end
-end
-
-// Read from PSG
-assign DO = dout;
-reg [7:0] dout;
-always_comb begin
- dout = 8'hFF;
- if(~BDIR & BC & !addr[7:4]) begin
- case(addr[3:0])
- 0: dout = ymreg[0];
- 1: dout = ymreg[1][3:0];
- 2: dout = ymreg[2];
- 3: dout = ymreg[3][3:0];
- 4: dout = ymreg[4];
- 5: dout = ymreg[5][3:0];
- 6: dout = ymreg[6][4:0];
- 7: dout = ymreg[7];
- 8: dout = ymreg[8][4:0];
- 9: dout = ymreg[9][4:0];
- 10: dout = ymreg[10][4:0];
- 11: dout = ymreg[11];
- 12: dout = ymreg[12];
- 13: dout = ymreg[13][3:0];
- 14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
- 15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
- endcase
- end
-end
-
-reg ena_div;
-reg ena_div_noise;
-
-// p_divider
-always @(posedge CLK) begin
- reg [3:0] cnt_div;
- reg noise_div;
-
- if(CE) begin
- ena_div <= 0;
- ena_div_noise <= 0;
- if(!cnt_div) begin
- cnt_div <= {SEL, 3'b111};
- ena_div <= 1;
-
- noise_div <= (~noise_div);
- if (noise_div) ena_div_noise <= 1;
- end else begin
- cnt_div <= cnt_div - 1'b1;
- end
- end
-end
-
-
-reg [2:0] noise_gen_op;
-
-// p_noise_gen
-always @(posedge CLK) begin
- reg [16:0] poly17;
- reg [4:0] noise_gen_cnt;
-
- if(CE) begin
- if (ena_div_noise) begin
- if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
- noise_gen_cnt <= 0;
- poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
- end else begin
- noise_gen_cnt <= noise_gen_cnt + 1'd1;
- end
- noise_gen_op <= {3{poly17[0]}};
- end
- end
-end
-
-wire [11:0] tone_gen_freq[1:3];
-assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
-assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
-assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
-
-reg [3:1] tone_gen_op;
-
-//p_tone_gens
-always @(posedge CLK) begin
- integer i;
- reg [11:0] tone_gen_cnt[1:3];
-
- if(CE) begin
- // looks like real chips count up - we need to get the Exact behaviour ..
-
- for (i = 1; i <= 3; i = i + 1) begin
- if(ena_div) begin
- if (tone_gen_freq[i]) begin
- if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
- tone_gen_cnt[i] <= 0;
- tone_gen_op[i] <= ~tone_gen_op[i];
- end else begin
- tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
- end
- end else begin
- tone_gen_op[i] <= ~ymreg[7][i];
- tone_gen_cnt[i] <= 0;
- end
- end
- end
- end
-end
-
-reg env_ena;
-wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
-
-//p_envelope_freq
-always @(posedge CLK) begin
- reg [15:0] env_gen_cnt;
-
- if(CE) begin
- env_ena <= 0;
- if(ena_div) begin
- if (env_gen_cnt >= env_gen_comp) begin
- env_gen_cnt <= 0;
- env_ena <= 1;
- end else begin
- env_gen_cnt <= (env_gen_cnt + 1'd1);
- end
- end
- end
-end
-
-reg [4:0] env_vol;
-
-wire is_bot = (env_vol == 5'b00000);
-wire is_bot_p1 = (env_vol == 5'b00001);
-wire is_top_m1 = (env_vol == 5'b11110);
-wire is_top = (env_vol == 5'b11111);
-
-always @(posedge CLK) begin
- reg env_hold;
- reg env_inc;
-
- // envelope shapes
- // C AtAlH
- // 0 0 x x \___
- //
- // 0 1 x x /___
- //
- // 1 0 0 0 \\\\
- //
- // 1 0 0 1 \___
- //
- // 1 0 1 0 \/\/
- // ___
- // 1 0 1 1 \
- //
- // 1 1 0 0 ////
- // ___
- // 1 1 0 1 /
- //
- // 1 1 1 0 /\/\
- //
- // 1 1 1 1 /___
-
- if(env_reset | RESET) begin
- // load initial state
- if(!ymreg[13][2]) begin // attack
- env_vol <= 5'b11111;
- env_inc <= 0; // -1
- end else begin
- env_vol <= 5'b00000;
- env_inc <= 1; // +1
- end
- env_hold <= 0;
- end
- else if(CE) begin
- if (env_ena) begin
- if (!env_hold) begin
- if (env_inc) env_vol <= (env_vol + 5'b00001);
- else env_vol <= (env_vol + 5'b11111);
- end
-
- // envelope shape control.
- if(!ymreg[13][3]) begin
- if(!env_inc) begin // down
- if(is_bot_p1) env_hold <= 1;
- end else if (is_top) env_hold <= 1;
- end else if(ymreg[13][0]) begin // hold = 1
- if(!env_inc) begin // down
- if(ymreg[13][1]) begin // alt
- if(is_bot) env_hold <= 1;
- end else if(is_bot_p1) env_hold <= 1;
- end else if(ymreg[13][1]) begin // alt
- if(is_top) env_hold <= 1;
- end else if(is_top_m1) env_hold <= 1;
- end else if(ymreg[13][1]) begin // alternate
- if(env_inc == 1'b0) begin // down
- if(is_bot_p1) env_hold <= 1;
- if(is_bot) begin
- env_hold <= 0;
- env_inc <= 1;
- end
- end else begin
- if(is_top_m1) env_hold <= 1;
- if(is_top) begin
- env_hold <= 0;
- env_inc <= 0;
- end
- end
- end
- end
- end
-end
-
-reg [5:0] A,B,C;
-always @(posedge CLK) begin
- A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
- B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
- C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
-end
-
-wire [7:0] volTable[64] = '{
- //YM2149
- 8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
- 8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
- 8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
- 8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
-
- //AY8910
- 8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
- 8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
- 8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
- 8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
-};
-
-assign CHANNEL_A = volTable[A];
-assign CHANNEL_B = volTable[B];
-assign CHANNEL_C = volTable[C];
-
-endmodule