mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 23:01:37 +03:00
194 lines
4.3 KiB
Systemverilog
194 lines
4.3 KiB
Systemverilog
//============================================================================
|
|
// Turbosound-FM
|
|
//
|
|
// Copyright (C) 2018 Ilia Sharin
|
|
// Copyright (C) 2018 Sorgelig
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
// more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
//============================================================================
|
|
|
|
|
|
module turbosound
|
|
(
|
|
input RESET, // Chip RESET (set all Registers to '0', active high)
|
|
input CLK, // Global clock
|
|
input CE, // YM2203 Master Clock enable
|
|
|
|
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 [11:0] CHANNEL_L, // Output channel L
|
|
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
|
|
);
|
|
|
|
|
|
reg RESET_s;
|
|
reg BDIR_s;
|
|
reg BC_s;
|
|
reg [7:0] DI_s;
|
|
|
|
always_ff @(posedge CLK) begin
|
|
reg RESET_d;
|
|
reg BDIR_d;
|
|
reg BC_d;
|
|
reg [7:0] DI_d;
|
|
|
|
RESET_d <= RESET;
|
|
BDIR_d <= BDIR;
|
|
BC_d <= BC;
|
|
DI_d <= DI;
|
|
|
|
RESET_s <= RESET_d;
|
|
BDIR_s <= BDIR_d;
|
|
BC_s <= BC_d;
|
|
DI_s <= DI_d;
|
|
end
|
|
|
|
|
|
// AY1 selected by default
|
|
reg ay_select = 1;
|
|
reg stat_sel = 1;
|
|
reg fm_ena = 0;
|
|
reg ym_wr = 0;
|
|
reg [7:0] ym_di;
|
|
|
|
always_ff @(posedge CLK or posedge RESET_s) begin
|
|
reg old_BDIR = 0;
|
|
reg ym_acc = 0;
|
|
|
|
if (RESET_s) begin
|
|
ay_select <= 1;
|
|
stat_sel <= 1;
|
|
fm_ena <= 0;
|
|
ym_acc <= 0;
|
|
ym_wr <= 0;
|
|
old_BDIR <= 0;
|
|
end
|
|
else begin
|
|
ym_wr <= 0;
|
|
old_BDIR <= BDIR_s;
|
|
if (~old_BDIR & BDIR_s) begin
|
|
if(BC_s & &DI_s[7:3]) begin
|
|
ay_select <= DI_s[0];
|
|
stat_sel <= DI_s[1];
|
|
fm_ena <= ~DI_s[2];
|
|
ym_acc <= 0;
|
|
end
|
|
else if(BC_s) begin
|
|
ym_acc <= !DI_s[7:4] || fm_ena;
|
|
ym_wr <= !DI_s[7:4] || fm_ena;
|
|
end
|
|
else begin
|
|
ym_wr <= ym_acc;
|
|
end
|
|
ym_di <= DI_s;
|
|
end
|
|
end
|
|
end
|
|
|
|
wire [7:0] psg_ch_a_0;
|
|
wire [7:0] psg_ch_b_0;
|
|
wire [7:0] psg_ch_c_0;
|
|
wire [15:0] opn_0;
|
|
wire [7:0] DO_0;
|
|
|
|
jt03 ym2203_0
|
|
(
|
|
.rst(RESET_s),
|
|
.clk(CLK),
|
|
.cen(CE),
|
|
.din(ym_di),
|
|
.addr((BDIR_s|ym_wr) ? ~BC_s : stat_sel),
|
|
.cs_n(ay_select),
|
|
.wr_n(~ym_wr),
|
|
.dout(DO_0),
|
|
|
|
.psg_A(psg_ch_a_0),
|
|
.psg_B(psg_ch_b_0),
|
|
.psg_C(psg_ch_c_0),
|
|
|
|
.fm_snd(opn_0)
|
|
);
|
|
|
|
wire [7:0] psg_ch_a_1;
|
|
wire [7:0] psg_ch_b_1;
|
|
wire [7:0] psg_ch_c_1;
|
|
wire [15:0] opn_1;
|
|
wire [7:0] DO_1;
|
|
|
|
jt03 ym2203_1
|
|
(
|
|
.rst(RESET_s),
|
|
.clk(CLK),
|
|
.cen(CE),
|
|
.din(ym_di),
|
|
.addr((BDIR_s|ym_wr) ? ~BC_s : stat_sel),
|
|
.cs_n(~ay_select),
|
|
.wr_n(~ym_wr),
|
|
.dout(DO_1),
|
|
|
|
.psg_A(psg_ch_a_1),
|
|
.psg_B(psg_ch_b_1),
|
|
.psg_C(psg_ch_c_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;
|
|
|
|
reg [8:0] sum_ch_a,sum_ch_b,sum_ch_c;
|
|
reg [7:0] psg_a,psg_b,psg_c;
|
|
reg [11:0] psg_l,psg_r,opn_s;
|
|
reg [11:0] ch_l, ch_r;
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
sum_ch_a <= { 1'b0, psg_ch_a_1 } + { 1'b0, psg_ch_a_0 };
|
|
sum_ch_b <= { 1'b0, psg_ch_b_1 } + { 1'b0, psg_ch_b_0 };
|
|
sum_ch_c <= { 1'b0, psg_ch_c_1 } + { 1'b0, psg_ch_c_0 };
|
|
|
|
psg_a <= sum_ch_a[8] ? 8'hFF : sum_ch_a[7:0];
|
|
psg_b <= sum_ch_b[8] ? 8'hFF : sum_ch_b[7:0];
|
|
psg_c <= sum_ch_c[8] ? 8'hFF : sum_ch_c[7:0];
|
|
|
|
psg_l <= {3'b000, psg_a, 1'd0} + {4'b0000, psg_b};
|
|
psg_r <= {3'b000, psg_c, 1'd0} + {4'b0000, psg_b};
|
|
opn_s <= {{2{opn_0[15]}}, opn_0[15:6]} + {{2{opn_1[15]}}, opn_1[15:6]};
|
|
|
|
ch_l <= fm_ena ? $signed(opn_s) + $signed(psg_l) : $signed(psg_l);
|
|
ch_r <= fm_ena ? $signed(opn_s) + $signed(psg_r) : $signed(psg_r);
|
|
end
|
|
|
|
assign CHANNEL_L = ch_l;
|
|
assign CHANNEL_R = ch_r;
|
|
|
|
endmodule
|