1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-03-02 01:30:39 +00:00
Files
Gehstock.Mist_FPGA/common/Sound/opl3/opl3fm.sv
2020-05-16 06:42:10 +02:00

264 lines
5.8 KiB
Systemverilog

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
// This file is part of the Next186 Soc PC project
// http://opencores.org/project,next186
//
// Filename: opl3seq.v
// Description: Part of the Next186 SoC PC project, OPL3
// Version 1.0
// Creation date: 13:55:57 02/27/2017
//
// Author: Nicolae Dumitrache
// e-mail: ndumitrache@opencores.org
//
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Nicolae Dumitrache
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source 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 Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, download it
// from http://www.opencores.org/lgpl.shtml
//
///////////////////////////////////////////////////////////////////////////////////
// Additional Comments:
//
// Port0 (R) = 4'b0000, Addr[1:0], qempty, ready
// Port1 (R) = Value[7:0], advance queue
//
///////////////////////////////////////////////////////////////////////////////////
//
// Improved reset stability and firmware portability by Sorgelig.
//
module opl3sw #(parameter OPLCLK = 50000000)
(
input reset,
// CPU interface
input cpu_clk,
input [1:0] addr,
input [7:0] din,
input wr,
// OPL sequencer
input clk, // 50Mhz (min 45Mhz)
output [15:0] left,
output [15:0] right
);
wire [7:0] ram_dout;
opl3_mem ram
(
.clk(clk),
.addr1(CPU_ADDR[12:0]),
.we1(CPU_MREQ & CPU_WR & CE),
.data_in1(CPU_DOUT),
.data_out1(ram_dout),
.addr2(OPL3Struct_base+seq_addr),
.we2(seq_wr),
.data_in2(seq_wdata),
.data_out2(seq_rdata)
);
wire [9:0] qdata;
wire qempty;
// show ahead fifo
opl3_fifo in_queue
(
.aclr(reset),
.wrclk(cpu_clk),
.data({addr, din}),
.wrreq(wr),
.rdclk(clk),
.q(qdata),
.rdreq(CE && CPU_IORQ && !CPU_WR && CPU_ADDR[0]),
.rdempty(qempty)
);
reg stb44100;
always @(posedge clk) begin
integer cnt;
localparam RATE = (OPLCLK/44100)-1;
cnt <= cnt+1;
if(cnt == RATE) cnt <= 0;
stb44100 <= !cnt;
end
wire seq_wr;
wire [11:0] seq_addr;
wire [15:0] seq_rdata;
wire [15:0] seq_wdata;
wire ready;
reg [11:0] OPL3Struct_base = 0;
reg seq_reset_n = 0;
always @(posedge clk) begin
if(reset) seq_reset_n <= 0;
if(CPU_IORQ & CPU_WR & CE) begin
if(CPU_ADDR[0]) {seq_reset_n, OPL3Struct_base[11:7]} <= {1'b1, CPU_DOUT[4:0]};
else OPL3Struct_base[6:0] <= CPU_DOUT[7:1];
end
end
opl3seq opl3seq
(
.clk(clk),
.reset(~seq_reset_n),
.rd(stb44100),
.A(A),
.B(B),
.ready(ready),
.ram_wr(seq_wr),
.ram_addr(seq_addr),
.ram_rdata(seq_rdata),
.ram_wdata(seq_wdata)
);
wire [15:0] A,B;
compressor compressor
(
clk,
stb44100,
A[15:4], B[15:4],
left, right
);
wire [15:0] CPU_ADDR;
wire [7:0] CPU_DOUT;
wire CPU_WR;
wire CPU_MREQ;
wire CPU_IORQ;
NextZ80 Z80
(
.DI(~CPU_IORQ ? ram_dout : CPU_ADDR[0] ? qdata[7:0] : {4'b0000, qdata[9:8], qempty, ready}),
.DO(CPU_DOUT),
.ADDR(CPU_ADDR),
.WR(CPU_WR),
.MREQ(CPU_MREQ),
.IORQ(CPU_IORQ),
.HALT(),
.M1(),
.CLK(clk),
.RESET(reset),
.INT(0),
.NMI(0),
.WAIT(!CE)
);
reg CE = 0;
always @(posedge clk) CE <= !CE;
endmodule
module opl3_mem
#(
parameter
DATA_WIDTH1 = 8,
ADDRESS_WIDTH1 = 13,
ADDRESS_WIDTH2 = 12,
INIT_FILE = "opl3prg.mem"
)
(
input clk,
input we1,
input [ADDRESS_WIDTH1-1:0] addr1,
input [DATA_WIDTH1-1:0] data_in1,
output reg [DATA_WIDTH1-1:0] data_out1,
input we2,
input [ADDRESS_WIDTH2-1:0] addr2,
input [DATA_WIDTH2-1:0] data_in2,
output reg [DATA_WIDTH2-1:0] data_out2
);
localparam RATIO = 1 << (ADDRESS_WIDTH1 - ADDRESS_WIDTH2);
localparam DATA_WIDTH2 = DATA_WIDTH1 * RATIO;
localparam RAM_DEPTH = 1 << ADDRESS_WIDTH2;
reg [RATIO-1:0] [DATA_WIDTH1-1:0] ram[0:RAM_DEPTH-1];
initial $readmemh(INIT_FILE, ram);
// Port A
always@(posedge clk) if(we1) ram[addr1 / RATIO][addr1 % RATIO] = data_in1;
always@(posedge clk) data_out1 <= ram[addr1 / RATIO][addr1 % RATIO];
// port B
always@(posedge clk) if(we2) ram[addr2] = data_in2;
always@(posedge clk) data_out2 <= ram[addr2];
endmodule
module opl3_fifo
(
input aclr,
input [9:0] data,
input rdclk,
input rdreq,
input wrclk,
input wrreq,
output [9:0] q,
output rdempty
);
dcfifo dcfifo_component (
.aclr (aclr),
.data (data),
.rdclk (rdclk),
.rdreq (rdreq),
.wrclk (wrclk),
.wrreq (wrreq),
.q (q),
.rdempty (rdempty),
.eccstatus (),
.rdfull (),
.rdusedw (),
.wrempty (),
.wrfull (),
.wrusedw ());
defparam
dcfifo_component.intended_device_family = "Cyclone V",
dcfifo_component.lpm_numwords = 1024,
dcfifo_component.lpm_showahead = "ON",
dcfifo_component.lpm_type = "dcfifo",
dcfifo_component.lpm_width = 10,
dcfifo_component.lpm_widthu = 10,
dcfifo_component.overflow_checking = "ON",
dcfifo_component.rdsync_delaypipe = 5,
dcfifo_component.read_aclr_synch = "ON",
dcfifo_component.underflow_checking = "ON",
dcfifo_component.use_eab = "ON",
dcfifo_component.write_aclr_synch = "ON",
dcfifo_component.wrsync_delaypipe = 5;
endmodule