Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Doom OPL3 detection, timing improvements #145

Merged
merged 3 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 24 additions & 6 deletions rtl/soc/sound/opl3/host_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,39 @@ module host_if
input wire wr_n,
input wire [1:0] address,
input wire [REG_FILE_DATA_WIDTH-1:0] din,
output logic [REG_FILE_DATA_WIDTH-1:0] dout,
output logic [REG_FILE_DATA_WIDTH-1:0] dout = 0,
output opl3_reg_wr_t opl3_reg_wr = 0,
input wire [REG_FILE_DATA_WIDTH-1:0] status,
output logic force_timer_overflow
);
logic cs_p1_n = 1;
logic wr_p1_n = 1;
logic [1:0] address_p1 = 0;
logic [REG_FILE_DATA_WIDTH-1:0] din_p1 = 0;
logic opl3_fifo_empty;
logic [1:0] opl3_address;
logic [REG_FILE_DATA_WIDTH-1:0] opl3_data;
logic wr;
logic wr_p1;
logic [REG_FILE_DATA_WIDTH-1:0] host_status;

always_comb wr = !cs_n && !wr_n;
// relax timing on clk_host
always_ff @(posedge clk_host) begin
cs_p1_n <= cs_n;
wr_p1_n <= wr_n;
address_p1 <= address;
din_p1 <= din;
end

always_comb wr_p1 = !cs_p1_n && !wr_p1_n;

afifo #(
.LGFIFO(6), // use at least 6 to get inferred into BRAM. Increase in ALMs at lower depths
.WIDTH(2 + REG_FILE_DATA_WIDTH) // address + data
) afifo (
.i_wclk(clk_host),
.i_wr_reset_n(ic_n),
.i_wr(wr), // edge detect if write is held for more than 1 cycle
.i_wr_data({address, din}),
.i_wr(wr_p1),
.i_wr_data({address_p1, din_p1}),
.o_wr_full(),
.i_rclk(clk),
.i_rd_reset_n(!reset),
Expand Down Expand Up @@ -104,9 +117,14 @@ module host_if
) dout_sync (
.clk(clk_host),
.in(status),
.out(dout)
.out(host_status)
);

// Doom DMXOPTION=-opl3-phase detection routine specifically reads address 'b10 to see if it's all ones
// Decompiled routine provided by Never_Again at https://www.vogons.org/viewtopic.php?f=7&t=100285
always_ff @(posedge clk_host)
dout <= address_p1 == 0 ? host_status : '1;

generate
if (INSTANTIATE_TIMERS)
trick_sw_detection trick_sw_detection (
Expand Down
54 changes: 36 additions & 18 deletions rtl/soc/sound/opl3/trick_sw_detection.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
# else
# $error("OPL3 not detected...");
#
# Think Volkswagon cheating on the diesel emmisions test by detecting they're under test, except this is to
# accomplish good. This works for Doom OPL detection under ao486MiSTer.
#
# CHANGE HISTORY:
# 12 April 2024 Greg Taylor
# Initial version
Expand Down Expand Up @@ -76,51 +79,66 @@ module trick_sw_detection
input wire [REG_FILE_DATA_WIDTH-1:0] din,
output logic force_timer_overflow
);
localparam NUM_READS_TO_TRIGGER_OVERFLOW = 20;
localparam NUM_READS_TO_TRIGGER_OVERFLOW = 50;

logic wr;
logic wr_p1 = 0;
logic cs_p1_n = 1;
logic wr_p1_n = 1;
logic rd_p1_n = 1;
logic [1:0] address_p1 = 0;
logic [REG_FILE_DATA_WIDTH-1:0] din_p1 = 0;
logic wr_p1;
logic [$clog2(NUM_READS_TO_TRIGGER_OVERFLOW)-1:0] host_rd_counter = 0;
opl3_reg_wr_t host_reg_wr;
logic rd;
logic rd_p1 = 0;
logic rd_p1;
logic rd_p2 = 0;
logic host_force_timer_overflow = 0;
logic start_counter = 0;
logic [REG_TIMER_WIDTH-1:0] timer1 = 0;

always_comb wr = !cs_n && !wr_n;
always_ff @(posedge clk_host) begin
cs_p1_n <= cs_n;
wr_p1_n <= wr_n;
rd_p1_n <= rd_n;
address_p1 <= address;
din_p1 <= din;
end

always_ff @(posedge clk_host)
wr_p1 <= wr;
always_comb wr_p1 = !cs_p1_n && !wr_p1_n;

always_ff @(posedge clk_host) begin
host_reg_wr.valid <= 0;

if (wr && !wr_p1)
if (!address[0]) begin // address write mode
host_reg_wr.bank_num <= address[1];
host_reg_wr.address <= din;
if (wr_p1)
if (!address_p1[0]) begin // address write mode
host_reg_wr.bank_num <= address_p1[1];
host_reg_wr.address <= din_p1;
end
else begin // data write mode
host_reg_wr.valid <= 1;
host_reg_wr.data <= din;
host_reg_wr.data <= din_p1;
end

if (!ic_n)
if (host_reg_wr.valid && host_reg_wr.bank_num == 0 && host_reg_wr.address == 'h2)
timer1 <= host_reg_wr.data;

if (!ic_n) begin
host_reg_wr <= 0;
timer1 <= 0;
end
end

always_comb rd = !cs_n && !rd_n;
always_comb rd_p1 = !cs_p1_n && !rd_p1_n;

always_ff @(posedge clk_host) begin
rd_p1 <= rd;
rd_p2 <= rd_p1;

if (host_reg_wr.valid && host_reg_wr.bank_num == 0 && host_reg_wr.address == 'h4 && host_reg_wr.data[0]) begin
if (host_reg_wr.valid && host_reg_wr.bank_num == 0 && host_reg_wr.address == 'h4 && host_reg_wr.data[0] && timer1 == 'hff) begin
start_counter <= 1;
host_rd_counter <= 0;
host_force_timer_overflow <= 0;
end

if (start_counter && rd && !rd_p1)
if (start_counter && rd_p1 && !rd_p2)
host_rd_counter <= host_rd_counter + 1;

if (host_rd_counter == NUM_READS_TO_TRIGGER_OVERFLOW)
Expand Down
4 changes: 2 additions & 2 deletions rtl/soc/sound/sound.v
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module sound
wire sb_read = read & sb_cs;
wire sb_write = write & sb_cs;

always @(posedge clk) readdata <= mixer_rd ? mixer_val : cms_rd ? data_from_cms : (!address[2:0]) ? (opl_dout | (fm_mode ? 8'h00 : 8'h06)) : data_from_dsp;
always @(posedge clk) readdata <= mixer_rd ? mixer_val : cms_rd ? data_from_cms : opl_cs ? (opl_dout | (fm_mode ? 8'h00 : 8'h06)) : data_from_dsp;

//------------------------------------------------------------------------------

Expand Down Expand Up @@ -155,7 +155,7 @@ wire opl_cs = ( address[2:1] == 0 && sb_cs) //220-221,228-229
|| (fm_mode && address[1] == 1 && fm_cs); //38A-38B

wire opl_wr = write && !cms_wr;
wire opl_rd = read && (address == 8);
wire opl_rd = read;

opl3 opl
(
Expand Down