diff --git a/PCXT.sv b/PCXT.sv index 7423b41..cdebecc 100644 --- a/PCXT.sv +++ b/PCXT.sv @@ -186,7 +186,6 @@ assign VGA_SCALER = 0; assign HDMI_FREEZE = 0; assign AUDIO_S = 1; -assign AUDIO_L = AUDIO_R; assign AUDIO_MIX = 0; assign LED_DISK = 0; @@ -209,6 +208,7 @@ localparam CONF_STR = { "O3,Model,IBM PCXT,Tandy 1000;", "-;", "OA,Adlib,On,Invisible;", + "OE,DSS/Covox,Unplugged,Plugged;", //"O4,CPU Speed,4.77Mhz,7.16Mhz;", "OB,Lo-tech 2MB EMS, Enabled, Disabled;", "OCD,EMS Frame,A000,C000,D000;", @@ -354,6 +354,18 @@ wire ce_pix; assign CLK_VIDEO = clk_28_636; assign CE_PIXEL = 1'b1; +reg cen_44100; +reg [31:0] cen_44100_cnt; +wire [31:0] cen_44100_cnt_next = cen_44100_cnt + 16'd44100; +always @(posedge CLK_50M) begin + cen_44100 <= 0; + cen_44100_cnt <= cen_44100_cnt_next; + if (cen_44100_cnt_next >= (50000000)) begin + cen_44100 <= 1; + cen_44100_cnt <= cen_44100_cnt_next - (50000000); + end +end + always @(posedge clk_28_636) clk_14_318 <= ~clk_14_318; // 14.318Mhz @@ -622,17 +634,18 @@ end .ps2_data (device_data), .ps2_clock_out (ps2_kbd_clk_out), .ps2_data_out (ps2_kbd_data_out), + .clk_en_44100 (cen_44100), + .dss_covox_en (status[14]), + .lclamp (AUDIO_L), + .rclamp (AUDIO_R), .clk_en_opl2 (cen_opl2), // clk_en_opl2 - .jtopl2_snd_e (jtopl2_snd_e), .adlibhide (adlibhide), .tandy_video (tandy_mode), - .tandy_snd_e (tandy_snd_e), .ioctl_download (ioctl_download), .ioctl_index (ioctl_index), .ioctl_wr (ioctl_wr), .ioctl_addr (ioctl_addr), - .ioctl_data (ioctl_data), - + .ioctl_data (ioctl_data), .clk_uart (clk_uart), .uart_rx (uart_rx), .uart_tx (uart_tx), @@ -659,23 +672,14 @@ end .ems_address (status[13:12]), .tandy_mode (tandy_mode) ); - - wire speaker_out; - wire [7:0] tandy_snd_e; - wire tandy_snd_rdy; - wire [15:0] jtopl2_snd_e; - wire [16:0]sndmix = (({jtopl2_snd_e[15], jtopl2_snd_e}) << 2) + (speaker_out << 15) + {tandy_snd_e, 6'd0}; // signed mixer - wire [15:0] SDRAM_DQ_IN; wire [15:0] SDRAM_DQ_OUT; wire SDRAM_DQ_IO; assign SDRAM_DQ_IN = SDRAM_DQ; assign SDRAM_DQ = ~SDRAM_DQ_IO ? SDRAM_DQ_OUT : 16'hZZZZ; - - assign AUDIO_R = sndmix >> 1; - + wire s6_3_mux; wire [2:0] SEGMENT; diff --git a/rtl/KFPC-XT/HDL/Chipset.sv b/rtl/KFPC-XT/HDL/Chipset.sv index 1920f2f..ec5da18 100644 --- a/rtl/KFPC-XT/HDL/Chipset.sv +++ b/rtl/KFPC-XT/HDL/Chipset.sv @@ -74,14 +74,16 @@ module CHIPSET ( input logic ps2_data, output logic ps2_clock_out, output logic ps2_data_out, + // SOUND + input logic clk_en_44100, // COVOX/DSS clock enable + input logic dss_covox_en, + output logic [15:0] lclamp, + output logic [15:0] rclamp, // JTOPL input logic clk_en_opl2, - output logic [15:0] jtopl2_snd_e, input logic adlibhide, // TANDY input logic tandy_video, - output logic [7:0] tandy_snd_e, - // IOCTL input logic ioctl_download, input logic [7:0] ioctl_index, @@ -265,10 +267,12 @@ module CHIPSET ( .ps2_data (ps2_data), .ps2_clock_out (ps2_clock_out), .ps2_data_out (ps2_data_out), + .clk_en_44100 (clk_en_44100), + .dss_covox_en (dss_covox_en), + .lclamp (lclamp), + .rclamp (rclamp), .clk_en_opl2 (clk_en_opl2), - .jtopl2_snd_e (jtopl2_snd_e), .adlibhide (adlibhide), - .tandy_snd_e (tandy_snd_e), .tandy_video (tandy_video), .tandy_snd_rdy (tandy_snd_rdy), .ioctl_download (ioctl_download), diff --git a/rtl/KFPC-XT/HDL/Peripherals.sv b/rtl/KFPC-XT/HDL/Peripherals.sv index 6c8746b..42af444 100644 --- a/rtl/KFPC-XT/HDL/Peripherals.sv +++ b/rtl/KFPC-XT/HDL/Peripherals.sv @@ -7,7 +7,7 @@ module PERIPHERALS #( ) ( input logic clock, input logic clk_sys, - input logic peripheral_clock, + input logic peripheral_clock, input logic reset, // CPU output logic interrupt_to_cpu, @@ -56,13 +56,16 @@ module PERIPHERALS #( input logic ps2_data, output logic ps2_clock_out, output logic ps2_data_out, + // SOUND + input logic clk_en_44100, // COVOX/DSS clock enable + input logic dss_covox_en, + output logic [15:0] lclamp, + output logic [15:0] rclamp, // JTOPL - input logic clk_en_opl2, - output logic [15:0] jtopl2_snd_e, + input logic clk_en_opl2, input logic adlibhide, // TANDY - input logic tandy_video, - output logic [7:0] tandy_snd_e, + input logic tandy_video, output logic tandy_snd_rdy, // IOCTL input logic ioctl_download, @@ -131,6 +134,7 @@ module PERIPHERALS #( wire xtide_select_n = ~(~iorq && ~address_enable_n && address[19:14] == 6'b111011); // EC000 - EFFFF (16 KB) wire uart_cs = (~address_enable_n && {address[15:3], 3'd0} == 16'h03F8); wire lpt_cs = (iorq && ~address_enable_n && {address[15:3], 3'd0} == 16'h0378); + wire lpt_ctl_cs = (iorq && ~address_enable_n && {address[15:3], 3'd0} == 16'h0379); wire [3:0] ems_page_address = (ems_address == 2'b00) ? 4'b1010 : (ems_address == 2'b01) ? 4'b1100 : 4'b1101; @@ -330,8 +334,9 @@ module PERIPHERALS #( end + wire [15:0] jtopl2_snd_e; wire [7:0] jtopl2_dout; - wire [7:0]opl32_data; + wire [7:0] opl32_data; assign opl32_data = adlibhide ? 8'hFF : jtopl2_dout; jtopl2 jtopl2_inst @@ -351,6 +356,7 @@ module PERIPHERALS #( // Tandy sound + wire [7:0] tandy_snd_e; sn76489_top sn76489 ( .clock_i(clock), @@ -361,7 +367,26 @@ module PERIPHERALS #( .ready_o(tandy_snd_rdy), .d_i(internal_data_bus), .aout_o(tandy_snd_e) - ); + ); + + wire dss_full; + soundwave sound_gen + ( + .CLK(clock), + .clk_en(clk_en_44100), + .data(internal_data_bus), + .we(dss_covox_en && lpt_cs && ~io_write_n), +// .word(WORD), + .speaker(speaker_out), + .tandy_snd(tandy_snd_e), + .opl2left(jtopl2_snd_e), + .opl2right(jtopl2_snd_e), +// .full(sq_full), // when not full, write max 2x1152 16bit samples + .dss_full(dss_full), + .lclamp(lclamp), + .rclamp(rclamp) + ); + logic keybord_interrupt_ff; always_ff @(posedge clock, posedge reset) begin @@ -724,6 +749,10 @@ module PERIPHERALS #( data_bus_out_from_chipset = 1'b1; data_bus_out = lpt_data; end + else if ((lpt_ctl_cs) && (~io_read_n)) begin + data_bus_out_from_chipset = 1'b1; + data_bus_out = {1'bx, dss_full, 6'bxxxxxx}; + end else begin data_bus_out_from_chipset = 1'b0; data_bus_out = 8'b00000000; diff --git a/rtl/common/common.qip b/rtl/common/common.qip index 866ab53..6e085e5 100644 --- a/rtl/common/common.qip +++ b/rtl/common/common.qip @@ -1,3 +1,5 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ram.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) clk_div3.v ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) bios.v ] \ No newline at end of file +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) bios.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) soundwave.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sndfifo.v ] \ No newline at end of file diff --git a/rtl/common/sndfifo.v b/rtl/common/sndfifo.v new file mode 100644 index 0000000..a054936 --- /dev/null +++ b/rtl/common/sndfifo.v @@ -0,0 +1,172 @@ +// megafunction wizard: %FIFO% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: dcfifo + +// ============================================================ +// File Name: sndfifo.v +// Megafunction Name(s): +// dcfifo +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 15.1.0 Build 185 10/21/2015 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 1991-2015 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus Prime License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module sndfifo ( + data, + rdclk, + rdreq, + wrclk, + wrreq, + q, + rdempty, + rdusedw, + wrusedw); + + input [31:0] data; + input rdclk; + input rdreq; + input wrclk; + input wrreq; + output [31:0] q; + output rdempty; + output [11:0] rdusedw; + output [11:0] wrusedw; + + wire [31:0] sub_wire0; + wire sub_wire1; + wire [11:0] sub_wire2; + wire [11:0] sub_wire3; + wire [31:0] q = sub_wire0[31:0]; + wire rdempty = sub_wire1; + wire [11:0] rdusedw = sub_wire2[11:0]; + wire [11:0] wrusedw = sub_wire3[11:0]; + + dcfifo dcfifo_component ( + .data (data), + .rdclk (rdclk), + .rdreq (rdreq), + .wrclk (wrclk), + .wrreq (wrreq), + .q (sub_wire0), + .rdempty (sub_wire1), + .rdusedw (sub_wire2), + .wrusedw (sub_wire3), + .aclr (), + .eccstatus (), + .rdfull (), + .wrempty (), + .wrfull ()); + defparam + dcfifo_component.intended_device_family = "Cyclone IV E", + dcfifo_component.lpm_numwords = 4096, + dcfifo_component.lpm_showahead = "OFF", + dcfifo_component.lpm_type = "dcfifo", + dcfifo_component.lpm_width = 32, + dcfifo_component.lpm_widthu = 12, + dcfifo_component.overflow_checking = "ON", + dcfifo_component.rdsync_delaypipe = 4, + dcfifo_component.underflow_checking = "ON", + dcfifo_component.use_eab = "ON", + dcfifo_component.wrsync_delaypipe = 4; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" +// Retrieval info: PRIVATE: Clock NUMERIC "4" +// Retrieval info: PRIVATE: Depth NUMERIC "4096" +// Retrieval info: PRIVATE: Empty NUMERIC "1" +// Retrieval info: PRIVATE: Full NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" +// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1" +// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" +// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0" +// Retrieval info: PRIVATE: Optimize NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0" +// Retrieval info: PRIVATE: UsedW NUMERIC "1" +// Retrieval info: PRIVATE: Width NUMERIC "32" +// Retrieval info: PRIVATE: dc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: diff_widths NUMERIC "0" +// Retrieval info: PRIVATE: msb_usedw NUMERIC "0" +// Retrieval info: PRIVATE: output_width NUMERIC "32" +// Retrieval info: PRIVATE: rsEmpty NUMERIC "1" +// Retrieval info: PRIVATE: rsFull NUMERIC "0" +// Retrieval info: PRIVATE: rsUsedW NUMERIC "1" +// Retrieval info: PRIVATE: sc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: sc_sclr NUMERIC "0" +// Retrieval info: PRIVATE: wsEmpty NUMERIC "0" +// Retrieval info: PRIVATE: wsFull NUMERIC "0" +// Retrieval info: PRIVATE: wsUsedW NUMERIC "1" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096" +// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF" +// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32" +// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12" +// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON" +// Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "4" +// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "4" +// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]" +// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]" +// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL "rdclk" +// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL "rdempty" +// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq" +// Retrieval info: USED_PORT: rdusedw 0 0 12 0 OUTPUT NODEFVAL "rdusedw[11..0]" +// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL "wrclk" +// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq" +// Retrieval info: USED_PORT: wrusedw 0 0 12 0 OUTPUT NODEFVAL "wrusedw[11..0]" +// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0 +// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0 +// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 +// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0 +// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0 +// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0 +// Retrieval info: CONNECT: rdusedw 0 0 12 0 @rdusedw 0 0 12 0 +// Retrieval info: CONNECT: wrusedw 0 0 12 0 @wrusedw 0 0 12 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL sndfifo.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL sndfifo.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL sndfifo.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL sndfifo.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL sndfifo_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL sndfifo_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf diff --git a/rtl/common/soundwave.v b/rtl/common/soundwave.v new file mode 100644 index 0000000..8384a94 --- /dev/null +++ b/rtl/common/soundwave.v @@ -0,0 +1,119 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +// This file is part of the Next186 Soc PC project +// http://opencores.org/project,next186 +// +// Filename: sound_gen.v +// Description: Part of the Next186 SoC PC project, +// stereo 2x16bit pulse density modulated sound generator +// 44100 samples/sec +// Disney Sound Source and Covox Speech compatible +// Version 1.0 +// Creation date: Jan2015 +// +// Author: Nicolae Dumitrache +// e-mail: ndumitrache@opencores.org +// +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015 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: +// +// byte write: both channels are the same (Covox emulation), the 8bit sample value is shifted by 8, the channel selector is reset to LEFT +// word write: LEFT first, the queue is updated only after RIGHT value is written +// sample rate: 44100Hz +////////////////////////////////////////////////////////////////////////////////// +`define SPKVOL 11 + +module soundwave( + input CLK, + input clk_en, +// input [15:0]data, + input [7:0]data, + input we, +// input word, + input speaker, + input [15:0]opl2left, + input [15:0]opl2right, + input [7:0]tandy_snd, + output full, // when not full, write max 2x1152 16bit samples + output dss_full, + output [15:0] lclamp, + output [15:0] rclamp + ); + + reg [31:0]wdata; + reg lr = 1'b0; + reg [2:0]write = 3'b000; + wire qempty; + wire [31:0]sample; + wire [31:0]sample1 = qempty ? 32'hc000c000 : sample; + reg [15:0]r_opl2left = 0; + reg [15:0]r_opl2right = 0; + wire [16:0]lmix = {sample1[15], sample1[15:0]} + {r_opl2left[15], r_opl2left} + {tandy_snd, 6'd0} + (speaker << `SPKVOL); // signed mixer left + wire [16:0]rmix = {sample1[31], sample1[31:16]} + {r_opl2right[15], r_opl2right} + {tandy_snd, 6'd0} + (speaker << `SPKVOL); // signed mixer right + assign lclamp = (~|lmix[16:15] | &lmix[16:15]) ? {!lmix[15], lmix[14:0]} : {16{!lmix[16]}}; // clamp to [-32768..32767] and add 32878 + assign rclamp = (~|rmix[16:15] | &rmix[16:15]) ? {!rmix[15], rmix[14:0]} : {16{!rmix[16]}}; + wire [11:0]wrusedw; + wire [11:0]rdusedw; + assign full = wrusedw >= 12'd2940; + assign dss_full = rdusedw > 12'd90; // Disney sound source queue full + + sndfifo sndfifo_inst + ( + .wrclk(CLK), // input wr_clk + .rdclk(CLK), // input rd_clk + .data(wdata), // input [31 : 0] din + .wrreq(|write), // input wr_en + .rdreq(clk_en), // input rd_en + .q(sample), // output [31 : 0] dout + .wrusedw(wrusedw), + .rdusedw(rdusedw), + .rdempty(qempty) // output empty + ); + + always @(posedge CLK) begin + r_opl2left <= opl2left; + r_opl2right <= opl2right; + if(we) begin + /* + if(word) begin + lr <= !lr; + write <= {2'b00, lr}; + if(lr) wdata[31:16] <= data; + else wdata[15:0] <= data; + end else begin + */ + lr <= 1'b0; // left + write <= 3'b110; + wdata <= {1'b1, data[7:0], 8'b00000001, data[7:0], 7'b0000000}; + end + else write <= write - |write; + end + + +endmodule