From ba7d903e12b2d370487227651cd3167e237ca826 Mon Sep 17 00:00:00 2001 From: Eugene Lozovoy Date: Tue, 10 Sep 2024 17:07:34 +0300 Subject: [PATCH] update JT12 --- files.qip | 1 - rtl/sound/jt12/jt03.qip | 70 +-- rtl/sound/jt12/jt03.v | 61 ++- rtl/sound/jt12/jt03_acc.v | 19 +- rtl/sound/jt12/jt12.v | 65 --- rtl/sound/jt12/jt12.vhd | 1 + rtl/sound/jt12/jt12_acc.v | 109 ---- rtl/sound/jt12/jt12_csr.v | 2 +- rtl/sound/jt12/jt12_div.v | 109 +++- rtl/sound/jt12/jt12_dout.v | 47 ++ rtl/sound/jt12/jt12_eg.v | 2 +- rtl/sound/jt12/jt12_eg_cnt.v | 4 +- rtl/sound/jt12/jt12_eg_ctrl.v | 16 +- rtl/sound/jt12/jt12_exprom.v | 3 +- rtl/sound/jt12/jt12_kon.v | 99 ++-- rtl/sound/jt12/jt12_lfo.v | 1 - rtl/sound/jt12/jt12_limitamp.v | 42 -- rtl/sound/jt12/jt12_mmr.v | 348 +++++++++---- rtl/sound/jt12/jt12_mmr_sim.vh | 854 ------------------------------- rtl/sound/jt12/jt12_mod.v | 19 +- rtl/sound/jt12/jt12_op.v | 286 ++--------- rtl/sound/jt12/jt12_pcm.v | 109 ---- rtl/sound/jt12/jt12_pg.v | 3 +- rtl/sound/jt12/jt12_pg_sum.v | 62 +-- rtl/sound/jt12/jt12_pm.v | 141 ++++- rtl/sound/jt12/jt12_reg.v | 103 ++-- rtl/sound/jt12/jt12_reg_ch.v | 128 +++++ rtl/sound/jt12/jt12_sh.v | 3 +- rtl/sound/jt12/jt12_sh24.v | 3 +- rtl/sound/jt12/jt12_sh_rst.v | 21 +- rtl/sound/jt12/jt12_single_acc.v | 17 +- rtl/sound/jt12/jt12_sumch.v | 1 - rtl/sound/jt12/jt12_timers.v | 217 ++++---- rtl/sound/jt12/jt12_top.v | 437 ++++++++++++---- rtl/sound/jt12/lfo_sh1_lut.hex | 64 --- rtl/sound/jt12/lfo_sh2_lut.hex | 64 --- rtl/sound/jt49/jt49.qip | 7 + rtl/sound/jt49/jt49.v | 258 ++++++++++ rtl/sound/jt49/jt49_bus.v | 105 ++++ rtl/sound/jt49/jt49_cen.v | 55 ++ rtl/sound/jt49/jt49_div.v | 52 ++ rtl/sound/jt49/jt49_eg.v | 88 ++++ rtl/sound/jt49/jt49_exp.v | 205 ++++++++ rtl/sound/jt49/jt49_noise.v | 62 +++ rtl/sound/turbosound.sv | 18 +- rtl/sound/ym2149.sv | 326 ------------ 46 files changed, 2259 insertions(+), 2448 deletions(-) delete mode 100644 rtl/sound/jt12/jt12.v delete mode 100644 rtl/sound/jt12/jt12_acc.v create mode 100644 rtl/sound/jt12/jt12_dout.v delete mode 100644 rtl/sound/jt12/jt12_limitamp.v delete mode 100644 rtl/sound/jt12/jt12_mmr_sim.vh delete mode 100644 rtl/sound/jt12/jt12_pcm.v create mode 100644 rtl/sound/jt12/jt12_reg_ch.v delete mode 100644 rtl/sound/jt12/lfo_sh1_lut.hex delete mode 100644 rtl/sound/jt12/lfo_sh2_lut.hex create mode 100644 rtl/sound/jt49/jt49.qip create mode 100644 rtl/sound/jt49/jt49.v create mode 100644 rtl/sound/jt49/jt49_bus.v create mode 100644 rtl/sound/jt49/jt49_cen.v create mode 100644 rtl/sound/jt49/jt49_div.v create mode 100644 rtl/sound/jt49/jt49_eg.v create mode 100644 rtl/sound/jt49/jt49_exp.v create mode 100644 rtl/sound/jt49/jt49_noise.v delete mode 100644 rtl/sound/ym2149.sv 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