Skip to content

Commit

Permalink
Fix Doom OPL3 detection, timing improvements (#145)
Browse files Browse the repository at this point in the history
* doom now picks up DMXOPTION=-opl3-phase

* relax timing a bit

* further timing improvement
  • Loading branch information
gtaylormb committed Apr 30, 2024
1 parent bfda576 commit fd0b76b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 26 deletions.
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

0 comments on commit fd0b76b

Please sign in to comment.