mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 23:01:37 +03:00
update JT12
This commit is contained in:
@ -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 ]
|
||||
|
@ -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
|
||||
endmodule // jt03
|
||||
|
@ -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 ),
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 27-12-2018
|
||||
|
||||
*/
|
||||
|
||||
// Wrapper to output only combined channels. Defaults to 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
|
@ -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
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
@ -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,
|
||||
|
@ -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
|
||||
|
47
rtl/sound/jt12/jt12_dout.v
Normal file
47
rtl/sound/jt12/jt12_dout.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
@ -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(
|
||||
|
@ -18,7 +18,6 @@
|
||||
Date: 25-2-2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
@ -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 ),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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,
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 2-11-2018
|
||||
|
||||
Based on information posted by Nemesis on:
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 2-11-2018
|
||||
|
||||
Based on information posted by Nemesis on:
|
||||
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||
|
||||
Based on jt51_phasegen.v, from JT51
|
||||
|
||||
*/
|
||||
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
|
@ -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 };
|
||||
|
@ -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
|
||||
|
128
rtl/sound/jt12/jt12_reg_ch.v
Normal file
128
rtl/sound/jt12/jt12_reg_ch.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<NUM_CH;i=i+1) begin
|
||||
reg_block[i] <= 0;
|
||||
reg_fnum [i] <= 0;
|
||||
reg_fb [i] <= 0;
|
||||
reg_alg [i] <= 0;
|
||||
reg_rl [i] <= 3;
|
||||
reg_ams [i] <= 0;
|
||||
reg_pms [i] <= 0;
|
||||
end else begin
|
||||
i = 0; // prevents latch warning in Quartus
|
||||
if( up_fnumlo ) { reg_block[ch_sel], reg_fnum[ch_sel] } <= {latch_fnum,din};
|
||||
if( up_alg ) begin
|
||||
reg_fb [ch_sel] <= din[5:3];
|
||||
reg_alg[ch_sel] <= din[2:0];
|
||||
end
|
||||
if( up_pms ) begin
|
||||
reg_rl [ch_sel] <= din[7:6];
|
||||
reg_ams[ch_sel] <= din[5:4];
|
||||
reg_pms[ch_sel] <= din[2:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -18,13 +18,12 @@
|
||||
Date: 1-31-2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// stages must be greater than 2
|
||||
module jt12_sh #(parameter width=5, stages=24 )
|
||||
(
|
||||
input clk,
|
||||
input clk_en,
|
||||
input clk_en /* synthesis direct_enable */,
|
||||
input [width-1:0] din,
|
||||
output [width-1:0] drop
|
||||
);
|
||||
|
@ -18,12 +18,11 @@
|
||||
Date: 1-31-2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module jt12_sh24 #(parameter width=5 )
|
||||
(
|
||||
input clk,
|
||||
input clk_en,
|
||||
input clk_en /* synthesis direct_enable */,
|
||||
input [width-1:0] din,
|
||||
output reg [width-1:0] st1,
|
||||
output reg [width-1:0] st2,
|
||||
|
@ -18,37 +18,26 @@
|
||||
Date: 1-31-2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
// stages must be greater than 2
|
||||
module jt12_sh_rst #(parameter width=5, stages=32, rstval=1'b0 )
|
||||
(
|
||||
input rst,
|
||||
input clk,
|
||||
input clk_en,
|
||||
input clk_en /* synthesis direct_enable */,
|
||||
input [width-1:0] din,
|
||||
output [width-1:0] drop
|
||||
);
|
||||
|
||||
reg [stages-1:0] bits[width-1:0];
|
||||
wire [width-1:0] din_mx = rst ? {width{rstval[0]}} : din;
|
||||
|
||||
genvar i;
|
||||
integer k;
|
||||
generate
|
||||
initial
|
||||
for (k=0; k < width; k=k+1) begin
|
||||
bits[k] = { stages{rstval}};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate
|
||||
for (i=0; i < width; i=i+1) begin: bit_shifter
|
||||
always @(posedge clk)
|
||||
if( rst ) begin
|
||||
bits[i] <= {stages{rstval}};
|
||||
end else if(clk_en) begin
|
||||
bits[i] <= {bits[i][stages-2:0], din[i]};
|
||||
end
|
||||
always @(posedge clk) if(clk_en) begin
|
||||
bits[i] <= {bits[i][stages-2:0], din_mx[i]};
|
||||
end
|
||||
assign drop[i] = bits[i][stages-1];
|
||||
end
|
||||
endgenerate
|
||||
|
@ -20,16 +20,19 @@
|
||||
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
// Accumulates an arbitrary number of inputs with saturation
|
||||
// restart the sum when input "zero" is high
|
||||
|
||||
module jt12_single_acc #(parameter win=14, // input data width
|
||||
|
||||
module jt12_single_acc #(parameter
|
||||
win=14, // input data width
|
||||
wout=16 // output data width
|
||||
)(
|
||||
input clk,
|
||||
input clk_en,
|
||||
input [win-1:0] op_result,
|
||||
input sum_en,
|
||||
input zero,
|
||||
input clk,
|
||||
input clk_en /* synthesis direct_enable */,
|
||||
input [win-1:0] op_result,
|
||||
input sum_en,
|
||||
input zero,
|
||||
output reg [wout-1:0] snd
|
||||
);
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
Date: 1-31-2017
|
||||
*/
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/* The input is {op[1:0], ch[2:0]}
|
||||
it adds 1 to the channel and overflow to the operator correctly */
|
||||
|
@ -1,113 +1,140 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 14-2-2017
|
||||
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<mult_max ) begin
|
||||
// mult not meant to overflow in this line
|
||||
{overflow, next } = { {1'b0, cnt}, mult+1'b1 } ;
|
||||
end else begin
|
||||
{overflow, next } = { {1'b0, cnt}+1'b1, {mult_width{1'b0}} };
|
||||
end
|
||||
init = { start_value, {mult_width{1'b0}} };
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst )
|
||||
zero2 <= 0;
|
||||
else if(clk_en) begin
|
||||
if( zero ) zero2 <= ~zero;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if( ~load || rst) begin
|
||||
mult <= { (mult_width){1'b0} };
|
||||
cnt <= start_value;
|
||||
end
|
||||
else if( clk_en )
|
||||
{ cnt, mult } <= overflow ? init : next;
|
||||
wire zero = num_ch == 6 ? zero : (zero2&zero);
|
||||
*/
|
||||
jt12_timer #(.CW(10)) timer_A(
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.cen ( clk_en ),
|
||||
.zero ( zero ),
|
||||
.start_value( value_A ),
|
||||
.load ( load_A ),
|
||||
.clr_flag ( clr_flag_A ),
|
||||
.flag ( flag_A ),
|
||||
.overflow ( overflow_A )
|
||||
);
|
||||
|
||||
jt12_timer #(.CW(8),.FREE_EN(1)) timer_B(
|
||||
.clk ( clk ),
|
||||
.rst ( rst ),
|
||||
.cen ( clk_en ),
|
||||
.zero ( zero ),
|
||||
.start_value( value_B ),
|
||||
.load ( load_B ),
|
||||
.clr_flag ( clr_flag_B ),
|
||||
.flag ( flag_B ),
|
||||
.overflow ( )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module jt12_timer #(parameter
|
||||
CW = 8, // counter bit width. This is the counter that can be loaded
|
||||
FW = 4, // number of bits for the free-running counter
|
||||
FREE_EN = 0 // enables a 4-bit free enable count
|
||||
) (
|
||||
input rst,
|
||||
input clk,
|
||||
input cen,
|
||||
input zero,
|
||||
input [CW-1:0] start_value,
|
||||
input load,
|
||||
input clr_flag,
|
||||
output reg flag,
|
||||
output reg overflow
|
||||
);
|
||||
/* verilator lint_off WIDTH */
|
||||
reg load_l;
|
||||
reg [CW-1:0] cnt, next;
|
||||
reg [FW-1:0] free_cnt, free_next;
|
||||
reg free_ov;
|
||||
|
||||
always@(posedge clk, posedge rst)
|
||||
if( rst )
|
||||
flag <= 1'b0;
|
||||
else /*if(cen)*/ begin
|
||||
if( clr_flag )
|
||||
flag <= 1'b0;
|
||||
else if( cen && zero && load && overflow ) flag<=1'b1;
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
{free_ov, free_next} = { 1'b0, free_cnt} + 1'b1;
|
||||
{overflow, next } = { 1'b0, cnt } + (FREE_EN ? free_ov : 1'b1);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
load_l <= load;
|
||||
if( !load_l && load ) begin
|
||||
cnt <= start_value;
|
||||
end else if( cen && zero && load )
|
||||
cnt <= overflow ? start_value : next;
|
||||
end
|
||||
|
||||
// Free running counter
|
||||
always @(posedge clk) begin
|
||||
if( rst ) begin
|
||||
free_cnt <= 0;
|
||||
end else if( cen && zero ) begin
|
||||
free_cnt <= free_next;
|
||||
end
|
||||
end
|
||||
/* verilator lint_on WIDTH */
|
||||
endmodule
|
||||
|
@ -12,47 +12,76 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JT12. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Author: Jose Tejada Gomez. Twitter: @topapate
|
||||
Version: 1.0
|
||||
Date: 14-2-2016
|
||||
|
||||
|
||||
Based on information posted by Nemesis on:
|
||||
http://gendev.spritesmind.net/forum/viewtopic.php?t=386&postdays=0&postorder=asc&start=167
|
||||
|
||||
Based on jt51_phasegen.v, from JT51
|
||||
|
||||
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
|
||||
|
@ -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
|
@ -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
|
7
rtl/sound/jt49/jt49.qip
Normal file
7
rtl/sound/jt49/jt49.qip
Normal file
@ -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 ]
|
258
rtl/sound/jt49/jt49.v
Normal file
258
rtl/sound/jt49/jt49.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
105
rtl/sound/jt49/jt49_bus.v
Normal file
105
rtl/sound/jt49/jt49_bus.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
55
rtl/sound/jt49/jt49_cen.v
Normal file
55
rtl/sound/jt49/jt49_cen.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
52
rtl/sound/jt49/jt49_div.v
Normal file
52
rtl/sound/jt49/jt49_div.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
88
rtl/sound/jt49/jt49_eg.v
Normal file
88
rtl/sound/jt49/jt49_eg.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
205
rtl/sound/jt49/jt49_exp.v
Normal file
205
rtl/sound/jt49/jt49_exp.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
62
rtl/sound/jt49/jt49_noise.v
Normal file
62
rtl/sound/jt49/jt49_noise.v
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
@ -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;
|
||||
|
@ -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
|
Reference in New Issue
Block a user