URL
https://opencores.org/ocsvn/psg16/psg16/trunk
Subversion Repositories psg16
Compare Revisions
- This comparison shows the changes necessary to convert path
/psg16/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/bench/PSG16_tb.v
0,0 → 1,168
`define PSG 64'hFFFF_FFFF_FFD5_0000 |
|
module PSG16_tb(); |
reg clk; |
reg rst; |
reg cyc; |
reg stb; |
wire ack; |
reg we; |
reg [63:0] adr; |
reg [15:0] dat; |
reg [7:0] state; |
wire [17:0] out; |
reg [31:0] cnt; |
|
initial begin |
rst = 0; |
clk = 0; |
#100 rst = 1; |
#100 rst = 0; |
end |
|
always #1 clk = ~clk; |
|
always @(posedge clk) |
if (rst) begin |
state <= 8'd0; |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
end |
else |
case (state) |
8'd0: state <= 8'd1; |
// Set master volume at 15 |
8'd1: |
if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= `PSG+128; |
dat <= 16'd15; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
state <= 8'd2; |
end |
// Set frequency to 800Hz |
8'd2: |
if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= `PSG; |
dat <= 16'd13422; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
state <= 8'd3; |
end |
// Set ADSR |
8'd3: |
if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= `PSG + 6; |
dat <= 16'hCA12; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
state <= 8'd4; |
end |
// Set gate,triangle wave,output enable |
8'd4: |
if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= `PSG + 4; |
dat <= 16'h1104; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
cnt <= 32'd0; |
state <= 8'd5; |
end |
// wait 1 second |
8'd5: |
if (cnt==32'd50000) |
state <= 8'd6; |
else |
cnt <= cnt + 1; |
// Set gate off,triangle wave,output enable |
8'd6: |
if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= `PSG + 4; |
dat <= 16'h0104; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
cnt <= 32'd0; |
state <= 8'd7; |
end |
// wait 1 second |
8'd7: |
if (cnt==32'd50000) |
state <= 8'd8; |
else |
cnt <= cnt + 1; |
// Set gate off,triangle wave,output enable |
8'd8: |
if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= `PSG + 4; |
dat <= 16'h0000; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
cnt <= 32'd0; |
state <= 8'd9; |
end |
default: ; |
endcase |
|
|
PSG16 #(.pClkDivide(50)) u1 |
( |
.rst_i(rst), |
.clk_i(clk), |
.cyc_i(cyc), |
.stb_i(stb), |
.ack_o(ack), |
.we_i(we), |
.sel_i(2'b11), |
.adr_i(adr), |
.dat_i(dat), |
.dat_o(), |
.vol_o(), |
.bg(), |
.m_cyc_o(), |
.m_stb_o(), |
.m_ack_i(), |
.m_we_o(), |
.m_sel_o(), |
.m_adr_o(), |
.m_dat_i(), |
.o(out) |
); |
|
endmodule |
/bench/AC97_tb.v
0,0 → 1,83
module AC97_tb(); |
reg rst; |
reg clk; |
wire BIT_CLK; |
wire RESET; |
wire SDATA_IN; |
wire SDATA_OUT; |
wire SYNC; |
|
reg cyc; |
reg stb; |
reg we; |
wire ack; |
reg [63:0] adr; |
reg [15:0] dat; |
wire [15:0] dato; |
|
initial begin |
#0 rst = 1'b0; |
#0 clk = 1'b0; |
#100 rst = 1'b1; |
#100 rst = 1'b0; |
end |
|
always #10 clk = ~clk; |
|
reg [7:0] state; |
always @(posedge clk) |
if (rst) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
state <= 8'd0; |
end |
else begin |
case(state) |
8'd0: state <= 8'd1; |
8'd1: if (!cyc) begin |
cyc <= 1'b1; |
stb <= 1'b1; |
we <= 1'b1; |
adr <= 64'hFFFF_FFFF_FFDC_1026; |
dat <= 16'h0000; |
end |
else if (ack) begin |
cyc <= 1'b0; |
stb <= 1'b0; |
we <= 1'b0; |
state <= 8'd2; |
end |
endcase |
end |
|
AC97 u1 |
( |
.rst_i(rst), |
.clk_i(clk), |
.cyc_i(cyc), |
.stb_i(stb), |
.ack_o(ack), |
.we_i(we), |
.adr_i(adr), |
.dat_i(dat), |
.dat_o(dato), |
.PSGout(), |
.BIT_CLK(BIT_CLK), |
.SYNC(SYNC), |
.SDATA_IN(SDATA_OUT), |
.SDATA_OUT(SDATA_IN), |
.RESET(RESET) |
); |
|
LM4550 u2 |
( |
.BIT_CLK(BIT_CLK), |
.SDATA_OUT(SDATA_OUT), |
.RESET(RESET), |
.SYNC(SYNC), |
.SDATA_IN(SDATA_IN) |
); |
|
|
endmodule |
/rtl/verilog/PSGChannelSummer.v
0,0 → 1,43
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// All rights reserved. |
// robfinch<remove>@opencores.org |
// |
// PSGChannelSummer.v |
// Sums the channel outputs. |
// |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
//============================================================================ |
|
module PSGChannelSummer(clk_i, cnt, outctrl, tmc_i, o); |
input clk_i; // master clock |
input [7:0] cnt; // select counter |
input [3:0] outctrl; // channel output enable control |
input [19:0] tmc_i; // time-multiplexed channel input |
output [21:0] o; // summed output |
reg [21:0] o; |
|
// channel select signal |
wire [1:0] sel = cnt[1:0]; |
|
always @(posedge clk_i) |
if (cnt==8'd0) |
o <= 22'd0 + (tmc_i & {20{outctrl[sel]}}); |
else if (cnt < 8'd4) |
o <= o + (tmc_i & {20{outctrl[sel]}}); |
|
endmodule |
/rtl/verilog/PSGEnvGen.v
0,0 → 1,356
/* ============================================================================ |
(C) 2007 Robert Finch |
All rights reserved. |
|
PSGEnvGen.v |
Version 1.1 |
|
ADSR envelope generator. |
|
This source code is available for evaluation and validation purposes |
only. This copyright statement and disclaimer must remain present in |
the file. |
|
|
NO WARRANTY. |
THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER |
EXPRESS OR IMPLIED. The user must assume the entire risk of using the |
Work. |
|
IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY |
INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO |
THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR. |
|
IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK |
IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN |
REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN |
LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU |
AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR |
LOSSES RELATING TO SUCH UNAUTHORIZED USE. |
|
|
Note that this envelope generator directly uses the values for attack, |
decay, sustain, and release. The original SID had to use four bit codes |
and lookup tables due to register limitations. This generator is |
built assuming there aren't any such register limitations. |
A wrapper could be built to provide that functionality. |
|
This component isn't really meant to be used in isolation. It is |
intended to be integrated into a larger audio component (eg SID |
emulator). The host component should take care of wrapping the control |
signals into a register array. |
|
The 'cnt' signal acts a prescaler used to determine the base frequency |
used to generate envelopes. The core expects to be driven at |
approximately a 1.0MHz rate for proper envelope generation. This is |
accomplished using the 'cnt' signal, which should the output of a |
counter used to divide the master clock frequency down to approximately |
a 1MHz rate. Therefore, the master clock frequency must be at least 4MHz |
for a 4 channel generator, 8MHZ for an 8 channel generator. The test |
system uses a 66.667MHz master clock and 'cnt' is the output of a seven |
bit counter that divides by 66. |
|
Note the resource space optimization. Rather than simply build a single |
channel ADSR envelope generator and instantiate it four or eight times, |
This unit uses a single envelope generator and time-multiplexes the |
controls from four (or eight) different channels. The ADSR is just |
complex enough that it's less expensive resource wise to multiplex the |
control signals. The luxury of time division multiplexing can be used |
here since audio signals are low frequency. The time division multiplex |
means that we need a clock that's four (or eight) times faster than |
would be needed if independent ADSR's were used. This probably isn't a |
problem for most cases. |
|
Spartan3 |
Webpack 9.1i xc3s1000-4ft256 |
522 LUTs / 271 slices / 81.155 MHz (speed) |
============================================================================ */ |
|
/* |
sample attack values / rates |
---------------------------- |
8 2ms |
32 8ms |
64 16ms |
96 24ms |
152 38ms |
224 56ms |
272 68ms |
320 80ms |
400 100ms |
955 239ms |
1998 500ms |
3196 800ms |
3995 1s |
12784 3.2s |
21174 5.3s |
31960 8s |
|
rate = 990.00ns x 256 x value |
*/ |
|
|
// envelope generator states |
`define ENV_IDLE 0 |
`define ENV_ATTACK 1 |
`define ENV_DECAY 2 |
`define ENV_SUSTAIN 3 |
`define ENV_RELEASE 4 |
|
// Envelope generator |
module PSGEnvGen(rst, clk, cnt, |
gate, |
attack0, attack1, attack2, attack3, |
decay0, decay1, decay2, decay3, |
sustain0, sustain1, sustain2, sustain3, |
relese0, relese1, relese2, relese3, |
o); |
parameter pChannels = 4; |
parameter pPrescalerBits = 8; |
input rst; // reset |
input clk; // core clock |
input [pPrescalerBits-1:0] cnt; // clock rate prescaler |
input [15:0] attack0; |
input [15:0] attack1; |
input [15:0] attack2; |
input [15:0] attack3; |
input [11:0] decay0; |
input [11:0] decay1; |
input [11:0] decay2; |
input [11:0] decay3; |
input [7:0] sustain0; |
input [7:0] sustain1; |
input [7:0] sustain2; |
input [7:0] sustain3; |
input [11:0] relese0; |
input [11:0] relese1; |
input [11:0] relese2; |
input [11:0] relese3; |
input [3:0] gate; |
output [7:0] o; |
|
reg [7:0] sustain; |
reg [15:0] attack; |
reg [17:0] decay; |
reg [17:0] relese; |
// Per channel count storage |
reg [7:0] envCtr [3:0]; |
reg [7:0] envCtr2 [3:0]; |
reg [7:0] iv [3:0]; // interval value for decay/release |
reg [2:0] icnt [3:0]; // interval count |
reg [19:0] envDvn [3:0]; |
reg [2:0] envState [3:0]; |
|
reg [2:0] envStateNxt; |
reg [15:0] envStepPeriod; // determines the length of one step of the envelope generator |
reg [7:0] envCtrx; |
reg [19:0] envDvnx; |
|
// Time multiplexed values |
wire [15:0] attack_x; |
wire [11:0] decay_x; |
wire [7:0] sustain_x; |
wire [11:0] relese_x; |
|
integer n; |
|
wire [1:0] sel = cnt[1:0]; |
|
mux4to1 #(16) u1 ( |
.e(1'b1), |
.s(sel), |
.i0(attack0), |
.i1(attack1), |
.i2(attack2), |
.i3(attack3), |
.z(attack_x) |
); |
|
mux4to1 #(12) u2 ( |
.e(1'b1), |
.s(sel), |
.i0(decay0), |
.i1(decay1), |
.i2(decay2), |
.i3(decay3), |
.z(decay_x) |
); |
|
mux4to1 #(8) u3 ( |
.e(1'b1), |
.s(sel), |
.i0(sustain0), |
.i1(sustain1), |
.i2(sustain2), |
.i3(sustain3), |
.z(sustain_x) |
); |
|
mux4to1 #(12) u4 ( |
.e(1'b1), |
.s(sel), |
.i0(relese0), |
.i1(relese1), |
.i2(relese2), |
.i3(relese3), |
.z(relese_x) |
); |
|
always @(attack_x) |
attack <= attack_x; |
|
always @(decay_x) |
decay <= decay_x; |
|
always @(sustain_x) |
sustain <= sustain_x; |
|
always @(relese_x) |
relese <= relese_x; |
|
|
always @(sel) |
envCtrx <= envCtr[sel]; |
|
always @(sel) |
envDvnx <= envDvn[sel]; |
|
|
// Envelope generate state machine |
// Determine the next envelope state |
always @(sel or gate or sustain) |
begin |
case (envState[sel]) |
`ENV_IDLE: |
if (gate[sel]) |
envStateNxt <= `ENV_ATTACK; |
else |
envStateNxt <= `ENV_IDLE; |
`ENV_ATTACK: |
if (envCtrx==8'hFE) begin |
if (sustain==8'hFF) |
envStateNxt <= `ENV_SUSTAIN; |
else |
envStateNxt <= `ENV_DECAY; |
end |
else |
envStateNxt <= `ENV_ATTACK; |
`ENV_DECAY: |
if (envCtrx==sustain) |
envStateNxt <= `ENV_SUSTAIN; |
else |
envStateNxt <= `ENV_DECAY; |
`ENV_SUSTAIN: |
if (~gate[sel]) |
envStateNxt <= `ENV_RELEASE; |
else |
envStateNxt <= `ENV_SUSTAIN; |
`ENV_RELEASE: begin |
if (envCtrx==8'h00) |
envStateNxt <= `ENV_IDLE; |
else if (gate[sel]) |
envStateNxt <= `ENV_SUSTAIN; |
else |
envStateNxt <= `ENV_RELEASE; |
end |
// In case of hardware problem |
default: |
envStateNxt <= `ENV_IDLE; |
endcase |
end |
|
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < pChannels; n = n + 1) |
envState[n] <= `ENV_IDLE; |
end |
else if (cnt < pChannels) |
envState[sel] <= envStateNxt; |
|
|
// Handle envelope counter |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < pChannels; n = n + 1) begin |
envCtr[n] <= 0; |
envCtr2[n] <= 0; |
icnt[n] <= 0; |
iv[n] <= 0; |
end |
end |
else if (cnt < pChannels) begin |
case (envState[sel]) |
`ENV_IDLE: |
begin |
envCtr[sel] <= 0; |
envCtr2[sel] <= 0; |
icnt[sel] <= 0; |
iv[sel] <= 0; |
end |
`ENV_SUSTAIN: |
begin |
envCtr2[sel] <= 0; |
icnt[sel] <= 0; |
iv[sel] <= sustain >> 3; |
end |
`ENV_ATTACK: |
begin |
icnt[sel] <= 0; |
iv[sel] <= (8'hff - sustain) >> 3; |
if (envDvnx==20'h0) begin |
envCtr2[sel] <= 0; |
envCtr[sel] <= envCtrx + 1; |
end |
end |
`ENV_DECAY, |
`ENV_RELEASE: |
if (envDvnx==20'h0) begin |
envCtr[sel] <= envCtrx - 1; |
if (envCtr2[sel]==iv[sel]) begin |
envCtr2[sel] <= 0; |
if (icnt[sel] < 3'd7) |
icnt[sel] <= icnt[sel] + 1; |
end |
else |
envCtr2[sel] <= envCtr2[sel] + 1; |
end |
endcase |
end |
|
// Determine envelope divider adjustment source |
always @(sel or attack or decay or relese) |
begin |
case(envState[sel]) |
`ENV_ATTACK: envStepPeriod <= attack; |
`ENV_DECAY: envStepPeriod <= decay; |
`ENV_RELEASE: envStepPeriod <= relese; |
default: envStepPeriod <= 16'h0; |
endcase |
end |
|
|
// double the delay at appropriate points |
// for exponential modelling |
wire [19:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt[sel]; |
|
|
// handle the clock divider |
// loadable down counter |
// This sets the period of each step of the envelope |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < pChannels; n = n + 1) |
envDvn[n] <= 0; |
end |
else if (cnt < pChannels) begin |
if (envDvnx==20'h0) |
envDvn[sel] <= envStepPeriod1; |
else |
envDvn[sel] <= envDvnx - 1; |
end |
|
assign o = envCtrx; |
|
endmodule |
|
|
/rtl/verilog/PSGShaper.v
0,0 → 1,41
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// All rights reserved. |
// robfinch<remove>@opencores.org |
// |
// PSGShaper.v |
// Shape the channels by applying the envelope to the tone generator |
// output. |
// |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// |
//============================================================================ */ |
|
module PSGShaper(clk_i, ce, tgi, env, o); |
input clk_i; // clock |
input ce; // clock enable |
input [11:0] tgi; // tone generator input |
input [7:0] env; // envelop generator input |
output [19:0] o; // shaped output |
reg [19:0] o; // shaped output |
|
// shape output according to envelope |
always @(posedge clk_i) |
if (ce) |
o <= tgi * env; |
|
endmodule |
/rtl/verilog/PSGMasterVolumeControl.v
0,0 → 1,46
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// All rights reserved. |
// robfinch<remove>@opencores.org |
// |
// PSGMasterVolumeControl.v |
// Controls the PSG's output volume. |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
//============================================================================ */ |
|
module PSGMasterVolumeControl(rst_i, clk_i, i, volume, o); |
input rst_i; |
input clk_i; |
input [15:0] i; |
input [3:0] volume; |
output [19:0] o; |
reg [19:0] o; |
|
// Multiply 16x4 bits |
wire [19:0] v1 = volume[0] ? i : 20'd0; |
wire [19:0] v2 = volume[1] ? {i,1'b0} + v1: v1; |
wire [19:0] v3 = volume[2] ? {i,2'b0} + v2: v2; |
wire [19:0] vo = volume[3] ? {i,3'b0} + v3: v3; |
|
always @(posedge clk_i) |
if (rst_i) |
o <= 20'b0; // Force the output volume to zero on reset |
else |
o <= vo; |
|
endmodule |
|
/rtl/verilog/PSGFilter.v
0,0 → 1,106
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// robfinch<remove>@opencores.org |
// All rights reserved. |
// |
// PSGFilter.v |
// Version 1.1 |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// |
// 16-tap digital filter |
// |
// Currently this filter is only partially tested. The author believes that |
// the approach used is valid however. |
// The author opted to include the filter because it is part of the design, |
// and even this untested component can provide an idea of the resource |
// requirements, and device capabilities. |
// This is a "how one might approach the problem" example, at least |
// until the author is sure the filter is working correctly. |
// |
// Time division multiplexing is used to implement this filter in order to |
// reduce the resource requirement. This should be okay because it is being |
// used to filter audio signals. The effective operating frequency of the |
// filter depends on the 'cnt' supplied (eg 1MHz) |
// |
// Spartan3 |
// Webpack 9.1i xc3s1000-4ft256 |
// 158 LUTs / 88 slices / 73.865MHz |
// 1 MULT |
//============================================================================ |
// |
module PSGFilter(rst, clk, cnt, wr, adr, din, i, o); |
parameter pTaps = 16; |
input rst; |
input clk; |
input [7:0] cnt; |
input wr; |
input [3:0] adr; |
input [12:0] din; |
input [14:0] i; |
output [14:0] o; |
reg [14:0] o; |
|
reg [30:0] acc; // accumulator |
reg [14:0] tap [0:pTaps-1]; // tap registers |
integer n; |
|
// coefficient memory |
reg [11:0] coeff [0:pTaps-1]; // magnitude of coefficient |
reg [pTaps-1:0] sgn; // sign of coefficient |
|
initial begin |
for (n = 0; n < pTaps; n = n + 1) |
begin |
coeff[n] <= 0; |
sgn[n] <= 0; |
end |
end |
|
// update coefficient memory |
always @(posedge clk) |
if (wr) begin |
coeff[adr] <= din[11:0]; |
sgn[adr] <= din[12]; |
end |
|
// shift taps |
// Note: infer a dsr by NOT resetting the registers |
always @(posedge clk) |
if (cnt==8'd0) begin |
tap[0] <= i; |
for (n = 1; n < pTaps; n = n + 1) |
tap[n] <= tap[n-1]; |
end |
|
wire [26:0] mult = coeff[cnt[3:0]] * tap[cnt[3:0]]; |
|
always @(posedge clk) |
if (rst) |
acc <= 0; |
else if (cnt==8'd0) |
acc <= sgn[cnt[3:0]] ? 0 - mult : 0 + mult; |
else if (cnt < pTaps) |
acc <= sgn[cnt[3:0]] ? acc - mult : acc + mult; |
|
always @(posedge clk) |
if (rst) |
o <= 0; |
else if (cnt==8'd0) |
o <= acc[30:16]; |
|
endmodule |
|
/rtl/verilog/PSG16.v
0,0 → 1,532
`timescale 1ns / 1ps |
//============================================================================= |
// (C) 2007,2010,2012 Robert Finch |
// robfinch<remove>@opencores.org |
// |
// PSG16.v |
// 4 Channel ADSR sound generator |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// |
// Registers |
// 0 ffffffff ffffffff freq [15:0] |
// 1 ----pppp pppppppp pulse width [11:0] |
// 2 trsg--fo -vvvvv-- test, ringmod, sync, gate, filter, output, voice type |
// vvvvv |
// wnpst |
// 3 ssssrrrr aaaadddd sustain,release,attack,decay |
// |
// ... |
// 64 -------- ----vvvv volume (0-15) |
// 65 nnnnnnnn nnnnnnnn osc3 oscillator 3 |
// 66 -------- nnnnnnnn env3 envelope 3 |
// 67 |
// 68 aa------ -------- wave table address a15-14 |
// 69 aaaaaaaa aaaaaaaa wave table address a31-16 |
// |
// 80-87 s---kkkk kkkkkkkk filter coefficients |
// 88-96 -------- -------- reserved for more filter coefficients |
// |
// |
// Spartan3 |
// Webpack 12.3 xc3s1200e-4fg320 |
// 1290 LUTs / 893 slices / 69.339 MHz |
// 1 Multipliers |
//============================================================================= |
|
module PSG16(rst_i, clk_i, cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o, |
vol_o, bg, |
m_cyc_o, m_stb_o, m_ack_i, m_we_o, m_sel_o, m_adr_o, m_dat_i, o |
); |
parameter pClkDivide = 66; |
|
// WISHBONE SYSCON |
input rst_i; |
input clk_i; // system clock |
// WISHBONE SLAVE |
input cyc_i; // cycle valid |
input stb_i; // circuit select |
output ack_o; |
input we_i; // write |
input [1:0] sel_i; // byte selects |
input [63:0] adr_i; // address input |
input [15:0] dat_i; // data input |
output [15:0] dat_o; // data output |
// WISHBONE MASTER |
output m_cyc_o; // bus request |
output m_stb_o; // strobe output |
input m_ack_i; |
output m_we_o; // write enable (always inactive) |
output [ 1:0] m_sel_o; // byte lane selects |
output [63:0] m_adr_o; // wave table address |
input [11:0] m_dat_i; // wave table data input |
|
output vol_o; |
|
input bg; // bus grant |
|
output [17:0] o; |
|
// I/O registers |
reg [15:0] dat_o; |
reg vol_o; |
reg [43:0] m_adr_o; |
|
reg [3:0] test; // test (enable note generator) |
reg [4:0] vt [3:0]; // voice type |
reg [15:0] freq0, freq1, freq2, freq3; // frequency control |
reg [11:0] pw0, pw1, pw2, pw3; // pulse width control |
reg [3:0] gate; |
reg [3:0] attack0, attack1, attack2, attack3; |
reg [3:0] decay0, decay1, decay2, decay3; |
reg [3:0] sustain0, sustain1, sustain2, sustain3; |
reg [3:0] relese0, relese1, relese2, relese3; |
reg [3:0] sync; |
reg [3:0] ringmod; |
reg [3:0] outctrl; |
reg [3:0] filt; // 1 = output goes to filter |
wire [23:0] acc0, acc1, acc2, acc3; |
reg [3:0] volume; // master volume |
wire [11:0] ngo; // not generator output |
wire [7:0] env; // envelope generator output |
wire [7:0] env3; |
wire [7:0] ibr; |
wire [7:0] ibg; |
wire [21:0] out1; |
reg [21:0] out1a; |
wire [19:0] out2; |
wire [21:0] out3; |
wire [19:0] out4; |
wire [21:0] filtin1; // FIR filter input |
wire [14:0] filt_o; // FIR filter output |
|
wire cs = cyc_i && stb_i && (adr_i[63:8]==56'hFFFF_FFFF_FFD5_00); |
assign m_cyc_o = |ibg & !m_ack_i; |
assign m_stb_o = m_cyc_o; |
assign m_we_o = 1'b0; |
assign m_sel_o = {m_cyc_o,m_cyc_o}; |
reg ack1; |
always @(posedge clk_i) |
ack1 <= cs & !ack1; |
assign ack_o = cs ? (we_i ? 1'b1 : ack1) : 1'b0; |
wire my_ack = m_ack_i; |
|
// write to registers |
always @(posedge clk_i) |
begin |
if (rst_i) begin |
freq0 <= 0; |
freq1 <= 0; |
freq2 <= 0; |
freq3 <= 0; |
pw0 <= 0; |
pw1 <= 0; |
pw2 <= 0; |
pw3 <= 0; |
test <= 0; |
vt[0] <= 0; |
vt[1] <= 0; |
vt[2] <= 0; |
vt[3] <= 0; |
gate <= 0; |
outctrl <= 0; |
filt <= 0; |
attack0 <= 0; |
attack1 <= 0; |
attack2 <= 0; |
attack3 <= 0; |
decay0 <= 0; |
sustain0 <= 0; |
relese0 <= 0; |
decay1 <= 0; |
sustain1 <= 0; |
relese1 <= 0; |
decay2 <= 0; |
sustain2 <= 0; |
relese2 <= 0; |
decay3 <= 0; |
sustain3 <= 0; |
relese3 <= 0; |
sync <= 0; |
ringmod <= 0; |
volume <= 0; |
m_adr_o[47:14] <= 34'b00000000_00000000_0000_0000_0000_0011_10; // 00038000 |
end |
else begin |
if (cs & we_i) begin |
case(adr_i[7:1]) |
//--------------------------------------------------------- |
7'd0: |
begin |
if (sel_i[0]) freq0[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) freq0[15:8] <= dat_i[15:8]; |
end |
7'd1: |
begin |
if (sel_i[0]) pw0[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) pw0[11:8] <= dat_i[11:8]; |
end |
7'd2: begin |
if (sel_i[0]) vt[0] <= dat_i[6:2]; |
if (sel_i[1]) begin |
outctrl[0] <= dat_i[8]; |
filt[0] <= dat_i[9]; |
gate[0] <= dat_i[12]; |
sync[0] <= dat_i[13]; |
ringmod[0] <= dat_i[14]; |
test[0] <= dat_i[15]; |
end |
end |
7'd3: begin |
if (sel_i[0]) attack0 <= dat_i[7:4]; |
if (sel_i[0]) decay0 <= dat_i[3:0]; |
if (sel_i[1]) relese0 <= dat_i[11:8]; |
if (sel_i[1]) sustain0 <= dat_i[15:12]; |
end |
|
//--------------------------------------------------------- |
7'd4: |
begin |
if (sel_i[0]) freq1[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) freq1[15:8] <= dat_i[15:8]; |
end |
7'd5: |
begin |
if (sel_i[0]) pw1[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) pw1[11:8] <= dat_i[11:8]; |
end |
7'd6: begin |
if (sel_i[0]) vt[1] <= dat_i[6:2]; |
if (sel_i[1]) begin |
outctrl[1] <= dat_i[8]; |
filt[1] <= dat_i[9]; |
gate[1] <= dat_i[12]; |
sync[1] <= dat_i[13]; |
ringmod[1] <= dat_i[14]; |
test[1] <= dat_i[15]; |
end |
end |
7'd7: begin |
if (sel_i[0]) attack1 <= dat_i[7:4]; |
if (sel_i[0]) decay1 <= dat_i[3:0]; |
if (sel_i[1]) relese1 <= dat_i[11:8]; |
if (sel_i[1]) sustain1 <= dat_i[15:12]; |
end |
|
//--------------------------------------------------------- |
7'd8: |
begin |
if (sel_i[0]) freq2[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) freq2[15:8] <= dat_i[15:8]; |
end |
7'd9: |
begin |
if (sel_i[0]) pw2[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) pw2[11:8] <= dat_i[11:8]; |
end |
7'd10: begin |
if (sel_i[0]) vt[2] <= dat_i[6:2]; |
if (sel_i[1]) begin |
outctrl[2] <= dat_i[8]; |
filt[2] <= dat_i[9]; |
gate[2] <= dat_i[12]; |
sync[2] <= dat_i[5]; |
outctrl[0] <= dat_i[13]; |
ringmod[2] <= dat_i[14]; |
test[2] <= dat_i[15]; |
end |
end |
7'd11: begin |
if (sel_i[0]) attack2 <= dat_i[7:4]; |
if (sel_i[0]) decay2 <= dat_i[3:0]; |
if (sel_i[1]) relese2 <= dat_i[11:8]; |
if (sel_i[1]) sustain2 <= dat_i[15:12]; |
end |
|
//--------------------------------------------------------- |
7'd12: |
begin |
if (sel_i[0]) freq3[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) freq3[15:8] <= dat_i[15:8]; |
end |
7'd13: |
begin |
if (sel_i[0]) pw3[ 7:0] <= dat_i[ 7:0]; |
if (sel_i[1]) pw3[11:8] <= dat_i[11:8]; |
end |
7'd14: begin |
if (sel_i[0]) vt[3] <= dat_i[6:2]; |
if (sel_i[1]) begin |
outctrl[3] <= dat_i[8]; |
filt[3] <= dat_i[9]; |
gate[3] <= dat_i[12]; |
sync[3] <= dat_i[13]; |
ringmod[3] <= dat_i[14]; |
test[3] <= dat_i[15]; |
end |
end |
7'd15: begin |
if (sel_i[0]) attack3 <= dat_i[7:4]; |
if (sel_i[0]) decay3 <= dat_i[3:0]; |
if (sel_i[1]) relese3 <= dat_i[11:8]; |
if (sel_i[1]) sustain3 <= dat_i[15:12]; |
end |
|
//--------------------------------------------------------- |
7'd64: if (sel_i[0]) volume <= dat_i[3:0]; |
|
7'd68: begin |
if (sel_i[1]) m_adr_o[15:14] <= dat_i[15:14]; |
end |
7'd69: |
begin |
if (sel_i[0]) m_adr_o[23:16] <= dat_i[ 7:0]; |
if (sel_i[1]) m_adr_o[31:24] <= dat_i[15:8]; |
end |
7'd70: begin |
if (sel_i[0]) m_adr_o[39:32] <= dat_i[ 7:0]; |
if (sel_i[1]) m_adr_o[47:40] <= dat_i[15:8]; |
end |
default: ; |
endcase |
end |
end |
end |
|
|
always @(posedge clk_i) |
if (cs) begin |
case(adr_i[6:0]) |
7'd65: begin |
vol_o <= 1'b1; |
dat_o <= acc3[23:8]; |
end |
7'd66: begin |
vol_o <= 1'b1; |
dat_o <= env3; |
end |
default: begin |
dat_o <= env3; |
vol_o <= 1'b0; |
end |
endcase |
end |
else begin |
dat_o <= 16'b0; |
vol_o <= 1'b0; |
end |
|
wire [11:0] alow; |
|
// set wave table output address |
always @(ibg or acc1 or acc0 or acc2 or acc3 or alow) |
begin |
m_adr_o[13:12] <= {ibg[2]|ibg[3],ibg[1]|ibg[3]}; |
m_adr_o[11:0] <= alow; |
end |
|
mux4to1 #(12) u11 |
( |
.e(1'b1), |
.s(m_adr_o[13:12]), |
.i0({acc0[23:13],1'b0}), |
.i1({acc1[23:13],1'b0}), |
.i2({acc2[23:13],1'b0}), |
.i3({acc3[23:13],1'b0}), |
.z(alow) |
); |
|
// This counter controls channel multiplexing and the base |
// operating frequency. |
wire [7:0] cnt; |
reg [7:0] cnt1,cnt2,cnt3; |
counter #(8) u1 |
( |
.rst(rst_i), |
.clk(clk_i), |
.ce(1'b1), |
.ld(cnt==pClkDivide-1), |
.d(8'd0), |
.q(cnt) |
); |
|
// channel select signal |
wire [1:0] sel = cnt[1:0]; |
|
|
// bus arbitrator for wave table access |
wire [2:0] bgn; |
PSGBusArb u2 |
( |
.rst(rst_i), |
.clk(clk_i), |
.ce(1'b1), |
.ack(1'b1), |
.seln(bgn), |
.req0(ibr[0]), |
.req1(ibr[1]), |
.req2(ibr[2]), |
.req3(ibr[3]), |
.req4(1'b0), |
.req5(1'b0), |
.req6(1'b0), |
.req7(1'b0), |
.sel0(ibg[0]), |
.sel1(ibg[1]), |
.sel2(ibg[2]), |
.sel3(ibg[3]), |
.sel4(), |
.sel5(), |
.sel6(), |
.sel7() |
); |
|
// note generator - multi-channel |
PSGNoteGen u3 |
( |
.rst(rst_i), |
.clk(clk_i), |
.cnt(cnt), |
.br(ibr), |
.bg(ibg), |
.ack(m_ack_i), |
.bgn(bgn), |
.test(test), |
.vt0(vt[0]), |
.vt1(vt[1]), |
.vt2(vt[2]), |
.vt3(vt[3]), |
.freq0(freq0), |
.freq1(freq1), |
.freq2(freq2), |
.freq3(freq3), |
.pw0(pw0), |
.pw1(pw1), |
.pw2(pw2), |
.pw3(pw3), |
.acc0(acc0), |
.acc1(acc1), |
.acc2(acc2), |
.acc3(acc3), |
.wave(m_dat_i), |
.sync(sync), |
.ringmod(ringmod), |
.o(ngo) |
); |
|
// envelope generator - multi-channel |
PSGEnvGen u4 |
( |
.rst(rst_i), |
.clk(clk_i), |
.cnt(cnt), |
.gate(gate), |
.attack0(attack0), |
.attack1(attack1), |
.attack2(attack2), |
.attack3(attack3), |
.decay0(decay0), |
.decay1(decay1), |
.decay2(decay2), |
.decay3(decay3), |
.sustain0(sustain0), |
.sustain1(sustain1), |
.sustain2(sustain2), |
.sustain3(sustain3), |
.relese0(relese0), |
.relese1(relese1), |
.relese2(relese2), |
.relese3(relese3), |
.o(env) |
); |
|
// shape output according to envelope |
PSGShaper u5 |
( |
.clk_i(clk_i), |
.ce(1'b1), |
.tgi(ngo), |
.env(env), |
.o(out2) |
); |
|
always @(posedge clk_i) |
cnt1 <= cnt; |
always @(posedge clk_i) |
cnt2 <= cnt1; |
always @(posedge clk_i) |
cnt3 <= cnt2; |
|
// Sum the channels not going to the filter |
PSGChannelSummer u6 |
( |
.clk_i(clk_i), |
.cnt(cnt1), |
.outctrl(outctrl), |
.tmc_i(out2), |
.o(out1) |
); |
|
always @(posedge clk_i) |
out1a <= out1; |
|
// Sum the channels going to the filter |
PSGChannelSummer u7 |
( |
.clk_i(clk_i), |
.cnt(cnt1), |
.outctrl(filt), |
.tmc_i(out2), |
.o(filtin1) |
); |
|
// The FIR filter |
PSGFilter u8 |
( |
.rst(rst_i), |
.clk(clk_i), |
.cnt(cnt2), |
.wr(we_i && stb_i && adr_i[6:4]==3'b101), |
.adr(adr_i[3:0]), |
.din({dat_i[15],dat_i[11:0]}), |
.i(filtin1[21:7]), |
.o(filt_o) |
); |
|
// Sum the filtered and unfiltered output |
PSGOutputSummer u9 |
( |
.clk_i(clk_i), |
.cnt(cnt3), |
.ufi(out1a), |
.fi({filt_o,7'b0}), |
.o(out3) |
); |
|
// Last stage: |
// Adjust output according to master volume |
PSGMasterVolumeControl u10 |
( |
.rst_i(rst_i), |
.clk_i(clk_i), |
.i(out3[21:6]), |
.volume(volume), |
.o(out4) |
); |
|
assign o = out4[19:2]; |
|
endmodule |
|
/rtl/verilog/mux4to1.v
0,0 → 1,46
// (C) 2007,2012 Robert T Finch |
// robfinch<remove>@opencores.org |
// All Rights Reserved. |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// Verilog 1995 |
// |
// Webpack 9.1i xc3s1000-4ft256 |
// slices / LUTs / MHz |
|
module mux4to1(e, s, i0, i1, i2, i3, z); |
parameter WID=4; |
input e; |
input [1:0] s; |
input [WID:1] i0; |
input [WID:1] i1; |
input [WID:1] i2; |
input [WID:1] i3; |
output [WID:1] z; |
reg [WID:1] z; |
|
always @(e or s or i0 or i1 or i2 or i3) |
if (!e) |
z <= {WID{1'b0}}; |
else begin |
case(s) |
2'b00: z <= i0; |
2'b01: z <= i1; |
2'b10: z <= i2; |
2'b11: z <= i3; |
endcase |
end |
|
endmodule |
/rtl/verilog/PSGNoteOutMux.v
0,0 → 1,51
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// robfinch<remove>@opencores.org |
// All rights reserved. |
// |
// PSGNoteOutMux.v |
// Version 1.0 |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// |
// Selects from one of five waveforms for output. Selected waveform |
// outputs are anded together. This is approximately how the |
// original SID worked. |
// |
// Spartan3 |
// Webpack 9.1i xc3s1000-4ft256 |
// 36 LUTs / 21 slices / 11ns |
//============================================================================ */ |
// |
module PSGNoteOutMux(s, a, b, c, d, e, o); |
parameter WID = 12; |
input [4:0] s; |
input [WID-1:0] a,b,c,d,e; |
output [WID-1:0] o; |
|
wire [WID-1:0] o1,o2,o3,o4,o5; |
|
assign o1 = s[4] ? e : {WID{1'b1}}; |
assign o2 = s[3] ? d : {WID{1'b1}}; |
assign o3 = s[2] ? c : {WID{1'b1}}; |
assign o4 = s[1] ? b : {WID{1'b1}}; |
assign o5 = s[0] ? a : {WID{1'b1}}; |
|
assign o = o1 & o2 & o3 & o4 & o5; |
|
endmodule |
|
|
/rtl/verilog/PSGOutputSummer.v
0,0 → 1,37
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// All rights reserved. |
// robfinch<remove>@opencores.org |
// |
// PSGOutputSummer.v |
// Sum the filtered and unfiltered output. |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
//============================================================================ */ |
|
module PSGOutputSummer(clk_i, cnt, ufi, fi, o); |
input clk_i; // master clock |
input [7:0] cnt; // clock divider |
input [21:0] ufi; // unfiltered audio input |
input [21:0] fi; // filtered audio input |
output [21:0] o; // summed output |
reg [21:0] o; |
|
always @(posedge clk_i) |
if (cnt==8'd0) |
o <= ufi + fi; |
|
endmodule |
/rtl/verilog/AC97Controller.v
0,0 → 1,429
`timescale 1ns / 1ps |
//============================================================================= |
// (C) 2012 Robert Finch |
// All rights reserved. |
// |
// AC97.v |
// AC97 controller interface to LM4550 |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
//============================================================================= |
|
// |
// This core uses a shadow register set that would be mapped into the I/O space |
// of the host controller to hold the contents of the LM4550 registers. The core |
// tracks updates to the LM4550 registers and writes the updates out as the |
// AC97 frame becomes available. |
// |
module AC97(rst_i, clk_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i, dat_o, |
PSGout, |
BIT_CLK, SYNC, SDATA_IN, SDATA_OUT, RESET |
); |
input rst_i; |
input clk_i; |
input cyc_i; |
input stb_i; |
output ack_o; |
input we_i; |
input [63:0] adr_i; |
input [15:0] dat_i; |
output [15:0] dat_o; |
reg [15:0] dat_o; |
|
input [17:0] PSGout; |
|
input BIT_CLK; |
output SYNC; |
input SDATA_IN; |
output SDATA_OUT; |
output RESET; |
|
wire cs = cyc_i && stb_i && (adr_i[63:8]==56'hFFFF_FFFF_FFDC_10); |
reg ack1; |
always @(posedge clk_i) |
ack1 <= cs & !ack1; |
assign ack_o = cs ? (we_i ? 1'b1 : ack1) : 1'b0; |
|
reg codecReady; |
reg [15:0] slot0; |
reg [19:0] slot1; |
reg [19:0] slot2; |
reg [19:0] slot3; |
reg [19:0] slot4; |
reg [19:0] slot5; |
reg [19:0] slot6; |
reg [19:0] slot7; |
reg [19:0] slot8; |
reg [19:0] slot9; |
reg [19:0] slot10; |
reg [19:0] slot11; |
reg [19:0] slot12; |
reg [4:0] rgno; |
|
wire [15:0] slot0i; |
wire [19:0] slot1i; |
wire [19:0] slot2i; |
reg [15:0] reg26; |
|
// There's really only 27 registers in the LM4550. A couple of address maps are |
// used to compress the register addresses so that a smaller shadow RAM can be |
// used. |
function [6:0] fnRealToLM4550RegMap; |
input [4:0] realreg; |
begin |
case(realreg) |
5'd0: fnRealToLM4550RegMap = 7'h00; |
5'd1: fnRealToLM4550RegMap = 7'h02; |
5'd2: fnRealToLM4550RegMap = 7'h04; |
5'd3: fnRealToLM4550RegMap = 7'h06; |
5'd4: fnRealToLM4550RegMap = 7'h0A; |
5'd5: fnRealToLM4550RegMap = 7'h0C; |
5'd6: fnRealToLM4550RegMap = 7'h0E; |
5'd7: fnRealToLM4550RegMap = 7'h10; |
5'd8: fnRealToLM4550RegMap = 7'h12; |
5'd9: fnRealToLM4550RegMap = 7'h14; |
5'd10: fnRealToLM4550RegMap = 7'h16; |
5'd11: fnRealToLM4550RegMap = 7'h18; |
5'd12: fnRealToLM4550RegMap = 7'h1A; |
5'd13: fnRealToLM4550RegMap = 7'h1C; |
5'd14: fnRealToLM4550RegMap = 7'h20; |
5'd15: fnRealToLM4550RegMap = 7'h22; |
5'd16: fnRealToLM4550RegMap = 7'h24; |
5'd17: fnRealToLM4550RegMap = 7'h26; |
5'd18: fnRealToLM4550RegMap = 7'h28; |
5'd19: fnRealToLM4550RegMap = 7'h2A; |
5'd20: fnRealToLM4550RegMap = 7'h2C; |
5'd21: fnRealToLM4550RegMap = 7'h32; |
5'd22: fnRealToLM4550RegMap = 7'h5A; |
5'd23: fnRealToLM4550RegMap = 7'h74; |
5'd24: fnRealToLM4550RegMap = 7'h7A; |
5'd25: fnRealToLM4550RegMap = 7'h7C; |
5'd26: fnRealToLM4550RegMap = 7'h7E; |
// These registers aren't part of the real LM4550 |
// They are provided as a scratchpad space. |
5'd27: fnRealToLM4550RegMap = 7'h60; |
5'd28: fnRealToLM4550RegMap = 7'h62; |
5'd29: fnRealToLM4550RegMap = 7'h64; |
5'd30: fnRealToLM4550RegMap = 7'h66; |
5'd31: fnRealToLM4550RegMap = 7'h68; |
default: fnRealToLM4550RegMap = 7'd00; |
endcase |
end |
endfunction |
|
function [4:0] fnLM4550ToRealRegMap; |
input [6:0] regno; |
begin |
case (regno) |
7'h00: fnLM4550ToRealRegMap = 5'd0; |
7'h02: fnLM4550ToRealRegMap = 5'd1; |
7'h04: fnLM4550ToRealRegMap = 5'd2; |
7'h06: fnLM4550ToRealRegMap = 5'd3; |
7'h0A: fnLM4550ToRealRegMap = 5'd4; |
7'h0C: fnLM4550ToRealRegMap = 5'd5; |
7'h0E: fnLM4550ToRealRegMap = 5'd6; |
7'h10: fnLM4550ToRealRegMap = 5'd7; |
7'h12: fnLM4550ToRealRegMap = 5'd8; |
7'h14: fnLM4550ToRealRegMap = 5'd9; |
7'h16: fnLM4550ToRealRegMap = 5'd10; |
7'h18: fnLM4550ToRealRegMap = 5'd11; |
7'h1A: fnLM4550ToRealRegMap = 5'd12; |
7'h1C: fnLM4550ToRealRegMap = 5'd13; |
7'h20: fnLM4550ToRealRegMap = 5'd14; |
7'h22: fnLM4550ToRealRegMap = 5'd15; |
7'h24: fnLM4550ToRealRegMap = 5'd16; |
7'h26: fnLM4550ToRealRegMap = 5'd17; |
7'h28: fnLM4550ToRealRegMap = 5'd18; |
7'h2A: fnLM4550ToRealRegMap = 5'd19; |
7'h2C: fnLM4550ToRealRegMap = 5'd20; |
7'h32: fnLM4550ToRealRegMap = 5'd21; |
7'h5A: fnLM4550ToRealRegMap = 5'd22; |
7'h74: fnLM4550ToRealRegMap = 5'd23; |
7'h7A: fnLM4550ToRealRegMap = 5'd24; |
7'h7C: fnLM4550ToRealRegMap = 5'd25; |
7'h7E: fnLM4550ToRealRegMap = 5'd26; |
// These registers aren't part of the real LM4550 |
// They are provided as a scratchpad space. |
7'h60: fnLM4550ToRealRegMap = 5'd27; |
7'h62: fnLM4550ToRealRegMap = 5'd28; |
7'h64: fnLM4550ToRealRegMap = 5'd29; |
7'h66: fnLM4550ToRealRegMap = 5'd30; |
7'h68: fnLM4550ToRealRegMap = 5'd31; |
default: fnLM4550ToRealRegMap = 5'd31; |
endcase |
end |
endfunction |
|
//--------------------------------------------------------------------- |
// Shadow registers |
//--------------------------------------------------------------------- |
reg [31:0] dirty; // Indicates which registers need to be written to the LM4550 |
reg [15:0] regfile [0:31]; // Mimic registers |
wire [15:0] rfrgno = regfile[rgno]; |
wire [15:0] rfadri = regfile[fnLM4550ToRealRegMap(adr_i[6:0])]; |
|
// Shadow register write |
always @(posedge clk_i) |
begin |
if (cs & we_i) begin |
regfile[fnLM4550ToRealRegMap(adr_i[6:0])] <= dat_i; |
end |
end |
|
// Shadow register read |
// Several of the LM4550 registers are read-only static values. |
// They are just hard-coded here. |
always @(posedge clk_i) |
if (cs) begin |
case (adr_i[6:0]) |
7'h00: dat_o <= 16'h0D50; |
7'h22: dat_o <= 16'h0101; |
7'h26: dat_o <= reg26; |
7'h5A: dat_o <= 16'h0000; |
7'h68: dat_o <= {16{|dirty}}; |
7'h74: dat_o <= 16'h0000; |
7'h7C: dat_o <= 16'h4E53; |
7'h7E: dat_o <= 16'h4350; |
default: dat_o <= rfadri; |
endcase |
end |
else |
dat_o <= 16'h0000; |
|
//--------------------------------------------------------------------- |
// Update to read LM4550 registers |
// |
// Only one register at a time may be written to the LM4550. Choose |
// a register based on which dirty bit is set. The dirty bit is reset |
// once the register is written to the LM4550. |
//--------------------------------------------------------------------- |
always @(posedge clk_i) |
casex(dirty) |
32'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd31; |
32'b01xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd30; |
32'b001xxxxxxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd29; |
32'b0001xxxxxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd28; |
32'b00001xxxxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd27; |
32'b000001xxxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd26; |
32'b0000001xxxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd25; |
32'b00000001xxxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd24; |
32'b000000001xxxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd23; |
32'b0000000001xxxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd22; |
32'b00000000001xxxxxxxxxxxxxxxxxxxxx: rgno <= 5'd21; |
32'b000000000001xxxxxxxxxxxxxxxxxxxx: rgno <= 5'd20; |
32'b0000000000001xxxxxxxxxxxxxxxxxxx: rgno <= 5'd19; |
32'b00000000000001xxxxxxxxxxxxxxxxxx: rgno <= 5'd18; |
32'b000000000000001xxxxxxxxxxxxxxxxx: rgno <= 5'd17; |
32'b0000000000000001xxxxxxxxxxxxxxxx: rgno <= 5'd16; |
32'b00000000000000001xxxxxxxxxxxxxxx: rgno <= 5'd15; |
32'b000000000000000001xxxxxxxxxxxxxx: rgno <= 5'd14; |
32'b0000000000000000001xxxxxxxxxxxxx: rgno <= 5'd13; |
32'b00000000000000000001xxxxxxxxxxxx: rgno <= 5'd12; |
32'b000000000000000000001xxxxxxxxxxx: rgno <= 5'd11; |
32'b0000000000000000000001xxxxxxxxxx: rgno <= 5'd10; |
32'b00000000000000000000001xxxxxxxxx: rgno <= 5'd9; |
32'b000000000000000000000001xxxxxxxx: rgno <= 5'd8; |
32'b0000000000000000000000001xxxxxxx: rgno <= 5'd7; |
32'b00000000000000000000000001xxxxxx: rgno <= 5'd6; |
32'b000000000000000000000000001xxxxx: rgno <= 5'd5; |
32'b0000000000000000000000000001xxxx: rgno <= 5'd4; |
32'b00000000000000000000000000001xxx: rgno <= 5'd3; |
32'b000000000000000000000000000001xx: rgno <= 5'd2; |
32'b0000000000000000000000000000001x: rgno <= 5'd1; |
32'b00000000000000000000000000000001: rgno <= 5'd0; |
default: rgno <= 5'd0; |
endcase |
|
// Detect an edge on the SYNC signal to determine when to populate a frame with |
// data. The AC97_controller streams continuously to the LM4550 at 48kHz frame |
// rate. |
edge_det u2 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(SYNC), .pe(pe_sync), .ne(), .ee() ); |
wire doRead = fnRealToLM4550RegMap(rgno)==7'h26; |
|
always @(posedge clk_i) |
if (rst_i) begin |
dirty <= 32'd0; |
slot0 <= 0; |
slot1 <= 0; |
slot2 <= 0; |
slot3 <= 0; |
slot4 <= 0; |
slot5 <= 0; |
slot6 <= 0; |
slot7 <= 0; |
slot8 <= 0; |
slot9 <= 0; |
slot10 <= 0; |
slot11 <= 0; |
slot12 <= 0; |
end |
else begin |
if (cs & we_i) |
dirty[fnLM4550ToRealRegMap(adr_i[6:0])] <= 1'b1; |
if (RESET) begin // RESET is active low! |
if (codecReady & pe_sync & |dirty) begin |
if (rgno < 7'd27) begin |
slot0[15] <= 1'b1; // frame is valid |
slot0[14] <= 1'b1; // valid control data |
slot0[13] <= 1'b1; // control data in slot2 |
slot0[12:0] <= 13'd0; |
slot1[19] <= doRead; // Write, 1= read |
slot1[18:12] <= fnRealToLM4550RegMap(rgno); |
slot1[11:0] <= 12'd0; // reserved |
slot2[19:4] <= doRead ? 16'h0000 : rfrgno; |
slot2[3:0] <= 4'd0; |
slot3 <= 20'd0; |
slot4 <= 20'd0; |
slot6 <= 20'd0; |
slot7 <= 20'd0; |
slot8 <= 20'd0; |
slot9 <= 20'd0; |
// these slots are always zero |
slot5 <= 20'd0; |
slot10 <= 20'd0; |
slot11 <= 20'd0; |
slot12 <= 20'd0; |
dirty[rgno] <= 1'b0; |
end |
else begin |
dirty[rgno] <= 1'b0; |
slot0[15] <= 1'b1; |
slot0[14] <= 1'b0; |
slot0[13] <= 1'b0; |
slot0[12] <= 1'b1; // left data in slot3 |
slot0[11] <= 1'b1; // right data in slot4 |
slot0[10:0] <= 11'd0; |
slot1 <= 20'd0; |
slot2 <= 20'd0; |
slot3[19:2] <= PSGout; |
slot3[1:0] <= 2'b00; |
slot4[19:2] <= PSGout; |
slot4[1:0] <= 2'b00; |
slot6 <= 20'd0; |
slot7 <= 20'd0; |
slot8 <= 20'd0; |
slot9 <= 20'd0; |
// these slots are always zero |
slot5 <= 20'd0; |
slot10 <= 20'd0; |
slot11 <= 20'd0; |
slot12 <= 20'd0; |
end |
end |
else if (codecReady & pe_sync) begin |
slot0[15] <= 1'b1; |
slot0[14] <= 1'b0; |
slot0[13] <= 1'b0; |
slot0[12] <= 1'b1; // left data in slot3 |
slot0[11] <= 1'b1; // right data in slot4 |
slot0[10:0] <= 11'd0; |
slot1 <= 20'd0; |
slot2 <= 20'd0; |
slot3[19:2] <= PSGout; |
slot3[1:0] <= 2'b00; |
slot4[19:2] <= PSGout; |
slot4[1:0] <= 2'b00; |
slot6 <= 20'd0; |
slot7 <= 20'd0; |
slot8 <= 20'd0; |
slot9 <= 20'd0; |
// these slots are always zero |
slot5 <= 20'd0; |
slot10 <= 20'd0; |
slot11 <= 20'd0; |
slot12 <= 20'd0; |
end |
// Send empty frames until the codec is ready. |
else if (pe_sync) begin |
slot0 <= 0; |
slot1 <= 0; |
slot2 <= 0; |
slot3 <= 0; |
slot4 <= 0; |
slot5 <= 0; |
slot6 <= 0; |
slot7 <= 0; |
slot8 <= 0; |
slot9 <= 0; |
slot10 <= 0; |
slot11 <= 0; |
slot12 <= 0; |
end |
end |
end |
|
always @(posedge clk_i) |
if (rst_i) begin |
reg26 <= 16'h0000; |
codecReady <= 1'b0; |
end |
else begin |
if (RESET) begin // RESET is active low! |
if (pe_sync) begin |
if (slot0i[15:13]==3'b111) begin |
if (slot1i[18:12]==7'h26) begin |
reg26 <= slot2i[19:4]; |
end |
end |
if (slot0i[15]==1'b1) begin |
codecReady <= 1'b1; |
end |
end |
end |
else |
codecReady <= 1'b0; |
end |
|
ac97_controller u1 |
( |
.SYSCLK(clk_i), // up to 125MHz |
.SYSTEM_RESET(rst_i), // active on 1 |
.BIT_CLK(BIT_CLK), // 12,288 MHz |
.SDATA_IN(SDATA_IN), |
.SYNC(SYNC), |
.SDATA_OUT(SDATA_OUT), |
.RESET(RESET), |
.DONE(), |
.Slot0_in(slot0), |
.Slot1_in(slot1), |
.Slot2_in(slot2), |
.Slot3_in(slot3), |
.Slot4_in(slot4), |
.Slot5_in(slot5), |
.Slot6_in(slot6), |
.Slot7_in(slot7), |
.Slot8_in(slot8), |
.Slot9_in(slot9), |
.Slot10_in(slot10), |
.Slot11_in(slot11), |
.Slot12_in(slot12), |
.Slot0_out(slot0i), |
.Slot1_out(slot1i), |
.Slot2_out(slot2i), |
.Slot3_out(), |
.Slot4_out(), |
// The following slots are not used, and they are always zero |
.Slot5_out(), |
.Slot6_out(), |
.Slot7_out(), |
.Slot8_out(), |
.Slot9_out(), |
.Slot10_out(), |
.Slot11_out(), |
.Slot12_out() |
); |
|
|
endmodule |
/rtl/verilog/PSGBusArb.v
0,0 → 1,183
`timescale 1ns / 1ps |
//============================================================================= |
// (C) 2007,2012 Robert Finch |
// robfinch<remove>@opencores.org |
// All rights reserved. |
// |
// PSGBusArb.v |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// Arbitrates access to the system bus among up to eight |
// wave table channels for the PSG. This arbitrator is part |
// of a tree that ends up looking like a single arbitration |
// request to the system. |
// |
// Spartan3 |
// 19 LUTs / 11 slices |
//============================================================================= |
|
module PSGBusArb(rst, clk, ce, ack, |
req0, req1, req2, req3, req4, req5, req6, req7, |
sel0, sel1, sel2, sel3, sel4, sel5, sel6, sel7, seln); |
input rst; // reset |
input clk; // clock (eg 100MHz) |
input ce; // clock enable (eg 25MHz) |
input ack; // bus transfer completed |
input req0; // requester 0 wants the bus |
input req1; // requester 1 wants the bus |
input req2; // ... |
input req3; |
input req4; |
input req5; |
input req6; |
input req7; |
output sel0; // requester 0 granted the bus |
reg sel0; |
output sel1; |
reg sel1; |
output sel2; |
reg sel2; |
output sel3; |
reg sel3; |
output sel4; |
reg sel4; |
output sel5; |
reg sel5; |
output sel6; |
reg sel6; |
output sel7; |
reg sel7; |
output [2:0] seln; // who has the bus |
reg [2:0] seln; |
|
always @(posedge clk) begin |
if (rst) begin |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd0; |
end |
else begin |
if (ce&ack) begin |
if (req0) begin |
sel0 <= 1'b1; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd0; |
end |
else if (req1) begin |
sel1 <= 1'b1; |
sel0 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd1; |
end |
else if (req2) begin |
sel2 <= 1'b1; |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd2; |
end |
else if (req3) begin |
sel3 <= 1'b1; |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd3; |
end |
else if (req4) begin |
sel4 <= 1'b1; |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd4; |
end |
else if (req5) begin |
sel5 <= 1'b1; |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel6 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd5; |
end |
else if (req6) begin |
sel6 <= 1'b1; |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel7 <= 1'b0; |
seln <= 3'd6; |
end |
else if (req7) begin |
sel7 <= 1'b1; |
sel0 <= 1'b0; |
sel1 <= 1'b0; |
sel2 <= 1'b0; |
sel3 <= 1'b0; |
sel4 <= 1'b0; |
sel5 <= 1'b0; |
sel6 <= 1'b0; |
seln <= 3'd7; |
end |
// otherwise, hold onto last owner |
else begin |
sel0 <= sel0; |
sel1 <= sel1; |
sel2 <= sel2; |
sel3 <= sel3; |
sel4 <= sel4; |
sel5 <= sel5; |
sel6 <= sel6; |
sel7 <= sel7; |
seln <= seln; |
end |
end |
end |
end |
|
endmodule |
/rtl/verilog/PSGEnvGenDec.v
0,0 → 1,495
`timescale 1ns / 1ps |
// ============================================================================ |
// (C) 2007,2012 Robert Finch |
// robfinch<remove>@opencores.org |
// All rights reserved. |
// |
// PSGEnvGen.v |
// Version 1.1 |
// |
// ADSR envelope generator. |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// |
// This component isn't really meant to be used in isolation. It is |
// intended to be integrated into a larger audio component (eg SID |
// emulator). The host component should take care of wrapping the control |
// signals into a register array. |
// |
// The 'cnt' signal acts a prescaler used to determine the base frequency |
// used to generate envelopes. The core expects to be driven at |
// approximately a 1.0MHz rate for proper envelope generation. This is |
// accomplished using the 'cnt' signal, which should the output of a |
// counter used to divide the master clock frequency down to approximately |
// a 1MHz rate. Therefore, the master clock frequency must be at least 4MHz |
// for a 4 channel generator, 8MHZ for an 8 channel generator. The test |
// system uses a 66.667MHz master clock and 'cnt' is the output of a seven |
// bit counter that divides by 66. |
// |
// Note the resource space optimization. Rather than simply build a single |
// channel ADSR envelope generator and instantiate it four or eight times, |
// This unit uses a single envelope generator and time-multiplexes the |
// controls from four (or eight) different channels. The ADSR is just |
// complex enough that it's less expensive resource wise to multiplex the |
// control signals. The luxury of time division multiplexing can be used |
// here since audio signals are low frequency. The time division multiplex |
// means that we need a clock that's four (or eight) times faster than |
// would be needed if independent ADSR's were used. This probably isn't a |
// problem for most cases. |
// |
// Spartan3 |
// Webpack 9.1i xc3s1000-4ft256 |
// 522 LUTs / 271 slices / 81.155 MHz (speed) |
//============================================================================ */ |
|
/* |
code sample attack values / rates |
--------------------------------- |
0 8 2ms |
1 32 8ms |
2 64 16ms |
3 96 24ms |
4 152 38ms |
5 224 56ms |
6 272 68ms |
7 320 80ms |
8 400 100ms |
9 955 239ms |
10 1998 500ms |
11 3196 800ms |
12 3995 1s |
13 12784 3.2s |
14 21174 5.3s |
15 31960 8s |
|
rate = 990.00ns x 256 x value |
*/ |
|
|
// envelope generator states |
`define ENV_IDLE 0 |
`define ENV_ATTACK 1 |
`define ENV_DECAY 2 |
`define ENV_SUSTAIN 3 |
`define ENV_RELEASE 4 |
|
//`define CHANNELS8 |
|
// Envelope generator |
module PSGEnvGen(rst, clk, cnt, |
gate, |
attack0, attack1, attack2, attack3, |
decay0, decay1, decay2, decay3, |
sustain0, sustain1, sustain2, sustain3, |
relese0, relese1, relese2, relese3, |
`ifdef CHANNELS8 |
attack4, attack5, attack6, attack7, |
decay4, decay5, decay6, decay7, |
sustain4, sustain5, sustain6, sustain7, |
relese4, relese5, relese6, relese7, |
`endif |
o); |
parameter pChannels = 4; |
parameter pPrescalerBits = 5; |
input rst; // reset |
input clk; // core clock |
input [pPrescalerBits-1:0] cnt; // clock rate prescaler |
input [3:0] attack0; |
input [3:0] attack1; |
input [3:0] attack2; |
input [3:0] attack3; |
input [3:0] decay0; |
input [3:0] decay1; |
input [3:0] decay2; |
input [3:0] decay3; |
input [3:0] sustain0; |
input [3:0] sustain1; |
input [3:0] sustain2; |
input [3:0] sustain3; |
input [3:0] relese0; |
input [3:0] relese1; |
input [3:0] relese2; |
input [3:0] relese3; |
`ifdef CHANNELS8 |
input [7:0] gate; |
input [3:0] attack4; |
input [3:0] attack5; |
input [3:0] attack6; |
input [3:0] attack7; |
input [3:0] decay4; |
input [3:0] decay5; |
input [3:0] decay6; |
input [3:0] decay7; |
input [3:0] sustain4; |
input [3:0] sustain5; |
input [3:0] sustain6; |
input [3:0] sustain7; |
input [3:0] relese4; |
input [3:0] relese5; |
input [3:0] relese6; |
input [3:0] relese7; |
`else |
input [3:0] gate; |
`endif |
output [7:0] o; |
|
reg [7:0] sustain; |
reg [15:0] attack; |
reg [17:0] decay; |
reg [17:0] relese; |
`ifdef CHANNELS8 |
reg [7:0] envCtr [7:0]; |
reg [7:0] envCtr2 [7:0]; // for counting intervals |
reg [7:0] iv[7:0]; // interval value for decay/release |
reg [2:0] icnt[7:0]; // interval count |
reg [19:0] envDvn [7:0]; |
reg [2:0] envState [7:0]; |
`else |
reg [7:0] envCtr [3:0]; |
reg [7:0] envCtr2 [3:0]; |
reg [7:0] iv[3:0]; // interval value for decay/release |
reg [2:0] icnt[3:0]; // interval count |
reg [19:0] envDvn [3:0]; |
reg [2:0] envState [3:0]; |
`endif |
reg [2:0] envStateNxt; |
reg [15:0] envStepPeriod; // determines the length of one step of the envelope generator |
reg [7:0] envCtrx; |
reg [19:0] envDvnx; |
|
wire [3:0] attack_x; |
wire [3:0] decay_x; |
wire [3:0] sustain_x; |
wire [3:0] relese_x; |
|
integer n; |
|
// Decodes a 4-bit code into an attack value |
function [15:0] AttackDecode; |
input [3:0] atk; |
|
begin |
case(atk) |
4'd0: AttackDecode = 16'd8; |
4'd1: AttackDecode = 16'd32; |
4'd2: AttackDecode = 16'd63; |
4'd3: AttackDecode = 16'd95; |
4'd4: AttackDecode = 16'd150; |
4'd5: AttackDecode = 16'd221; |
4'd6: AttackDecode = 16'd268; |
4'd7: AttackDecode = 16'd316; |
4'd8: AttackDecode = 16'd395; |
4'd9: AttackDecode = 16'd986; |
4'd10: AttackDecode = 16'd1973; |
4'd11: AttackDecode = 16'd3157; |
4'd12: AttackDecode = 16'd3946; |
4'd13: AttackDecode = 16'd11837; |
4'd14: AttackDecode = 16'd19729; |
4'd15: AttackDecode = 16'd31566; |
endcase |
end |
|
endfunction |
|
// Decodes a 4-bit code into a decay/release value |
function [15:0] DecayDecode; |
input [3:0] dec; |
|
begin |
case(dec) |
4'd0: DecayDecode = 17'd24; |
4'd1: DecayDecode = 17'd95; |
4'd2: DecayDecode = 17'd190; |
4'd3: DecayDecode = 17'd285; |
4'd4: DecayDecode = 17'd452; |
4'd5: DecayDecode = 17'd665; |
4'd6: DecayDecode = 17'd808; |
4'd7: DecayDecode = 17'd951; |
4'd8: DecayDecode = 17'd1188; |
4'd9: DecayDecode = 17'd2971; |
4'd10: DecayDecode = 17'd5942; |
4'd11: DecayDecode = 17'd9507; |
4'd12: DecayDecode = 17'd11884; |
4'd13: DecayDecode = 17'd35651; |
4'd14: DecayDecode = 17'd59418; |
4'd15: DecayDecode = 17'd95068; |
endcase |
end |
|
endfunction |
|
`ifdef CHANNELS8 |
wire [2:0] sel = cnt[2:0]; |
|
always @(sel or |
attack0 or attack1 or attack2 or attack3 or |
attack4 or attack5 or attack6 or attack7) |
case (sel) |
0: attack_x <= attack0; |
1: attack_x <= attack1; |
2: attack_x <= attack2; |
3: attack_x <= attack3; |
4: attack_x <= attack4; |
5: attack_x <= attack5; |
6: attack_x <= attack6; |
7: attack_x <= attack7; |
endcase |
|
always @(sel or |
decay0 or decay1 or decay2 or decay3 or |
decay4 or decay5 or decay6 or decay7) |
case (sel) |
0: decay_x <= decay0; |
1: decay_x <= decay1; |
2: decay_x <= decay2; |
3: decay_x <= decay3; |
4: decay_x <= decay4; |
5: decay_x <= decay5; |
6: decay_x <= decay6; |
7: decay_x <= decay7; |
endcase |
|
always @(sel or |
sustain0 or sustain1 or sustain2 or sustain3 or |
sustain4 or sustain5 or sustain6 or sustain7) |
case (sel) |
0: sustain <= sustain0; |
1: sustain <= sustain1; |
2: sustain <= sustain2; |
3: sustain <= sustain3; |
4: sustain <= sustain4; |
5: sustain <= sustain5; |
6: sustain <= sustain6; |
7: sustain <= sustain7; |
endcase |
|
always @(sel or |
relese0 or relese1 or relese2 or relese3 or |
relese4 or relese5 or relese6 or relese7) |
case (sel) |
0: relese <= relese0; |
1: relese <= relese1; |
2: relese <= relese2; |
3: relese <= relese3; |
4: relese <= relese4; |
5: relese <= relese5; |
6: relese <= relese6; |
7: relese <= relese7; |
endcase |
|
`else |
|
wire [1:0] sel = cnt[1:0]; |
|
mux4to1 #(4) u1 ( |
.e(1'b1), |
.s(sel), |
.i0(attack0), |
.i1(attack1), |
.i2(attack2), |
.i3(attack3), |
.z(attack_x) |
); |
|
mux4to1 #(12) u2 ( |
.e(1'b1), |
.s(sel), |
.i0(decay0), |
.i1(decay1), |
.i2(decay2), |
.i3(decay3), |
.z(decay_x) |
); |
|
mux4to1 #(8) u3 ( |
.e(1'b1), |
.s(sel), |
.i0(sustain0), |
.i1(sustain1), |
.i2(sustain2), |
.i3(sustain3), |
.z(sustain_x) |
); |
|
mux4to1 #(12) u4 ( |
.e(1'b1), |
.s(sel), |
.i0(relese0), |
.i1(relese1), |
.i2(relese2), |
.i3(relese3), |
.z(relese_x) |
); |
|
`endif |
|
always @(attack_x) |
attack <= AttackDecode(attack_x); |
|
always @(decay_x) |
decay <= DecayDecode(decay_x); |
|
always @(sustain_x) |
sustain <= {sustain_x,sustain_x}; |
|
always @(relese_x) |
relese <= DecayDecode(relese_x); |
|
|
always @(sel) |
envCtrx <= envCtr[sel]; |
|
always @(sel) |
envDvnx <= envDvn[sel]; |
|
|
// Envelope generate state machine |
// Determine the next envelope state |
always @(sel or gate or sustain) |
begin |
case (envState[sel]) |
`ENV_IDLE: |
if (gate[sel]) |
envStateNxt <= `ENV_ATTACK; |
else |
envStateNxt <= `ENV_IDLE; |
`ENV_ATTACK: |
if (envCtrx==8'hFE) begin |
if (sustain==8'hFF) |
envStateNxt <= `ENV_SUSTAIN; |
else |
envStateNxt <= `ENV_DECAY; |
end |
else |
envStateNxt <= `ENV_ATTACK; |
`ENV_DECAY: |
if (envCtrx==sustain) |
envStateNxt <= `ENV_SUSTAIN; |
else |
envStateNxt <= `ENV_DECAY; |
`ENV_SUSTAIN: |
if (~gate[sel]) |
envStateNxt <= `ENV_RELEASE; |
else |
envStateNxt <= `ENV_SUSTAIN; |
`ENV_RELEASE: begin |
if (envCtrx==8'h00) |
envStateNxt <= `ENV_IDLE; |
else if (gate[sel]) |
envStateNxt <= `ENV_SUSTAIN; |
else |
envStateNxt <= `ENV_RELEASE; |
end |
// In case of hardware problem |
default: |
envStateNxt <= `ENV_IDLE; |
endcase |
end |
|
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < pChannels; n = n + 1) |
envState[n] <= `ENV_IDLE; |
end |
else if (cnt < pChannels) |
envState[sel] <= envStateNxt; |
|
|
// Handle envelope counter |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < pChannels; n = n + 1) begin |
envCtr[n] <= 0; |
envCtr2[n] <= 0; |
icnt[n] <= 0; |
iv[n] <= 0; |
end |
end |
else if (cnt < pChannels) begin |
case (envState[sel]) |
`ENV_IDLE: |
begin |
envCtr[sel] <= 0; |
envCtr2[sel] <= 0; |
icnt[sel] <= 0; |
iv[sel] <= 0; |
end |
`ENV_SUSTAIN: |
begin |
envCtr2[sel] <= 0; |
icnt[sel] <= 0; |
iv[sel] <= sustain >> 3; |
end |
`ENV_ATTACK: |
begin |
icnt[sel] <= 0; |
iv[sel] <= (8'hff - sustain) >> 3; |
if (envDvnx==20'h0) begin |
envCtr2[sel] <= 0; |
envCtr[sel] <= envCtrx + 1; |
end |
end |
`ENV_DECAY, |
`ENV_RELEASE: |
if (envDvnx==20'h0) begin |
envCtr[sel] <= envCtrx - 1; |
if (envCtr2[sel]==iv[sel]) begin |
envCtr2[sel] <= 0; |
if (icnt[sel] < 3'd7) |
icnt[sel] <= icnt[sel] + 1; |
end |
else |
envCtr2[sel] <= envCtr2[sel] + 1; |
end |
endcase |
end |
|
// Determine envelope divider adjustment source |
always @(sel or attack or decay or relese) |
begin |
case(envState[sel]) |
`ENV_ATTACK: envStepPeriod <= attack; |
`ENV_DECAY: envStepPeriod <= decay; |
`ENV_RELEASE: envStepPeriod <= relese; |
default: envStepPeriod <= 16'h0; |
endcase |
end |
|
|
// double the delay at appropriate points |
// for exponential modelling |
wire [19:0] envStepPeriod1 = {4'b0,envStepPeriod} << icnt[sel]; |
|
|
// handle the clock divider |
// loadable down counter |
// This sets the period of each step of the envelope |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < pChannels; n = n + 1) |
envDvn[n] <= 0; |
end |
else if (cnt < pChannels) begin |
if (envDvnx==20'h0) |
envDvn[sel] <= envStepPeriod1; |
else |
envDvn[sel] <= envDvnx - 1; |
end |
|
assign o = envCtrx; |
|
endmodule |
|
|
/rtl/verilog/PSGNoteGen.v
0,0 → 1,191
`timescale 1ns / 1ps |
//============================================================================= |
// (C) 2007,2012 Robert Finch |
// robfinch<remove>@opencores.org |
// All rights reserved. |
// |
// PSGNoteGen.v |
// Version 1.1 |
// |
// 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 3 of the License, or |
// (at your option) any later version. |
// |
// This source file 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, see <http://www.gnu.org/licenses/>. |
// |
// |
// Note generator. 4/8 channels |
// |
// Spartan3 |
// Webpack 9.1i xc3s1000-4ft256 |
// 337 LUTs / 224 slices / 98.445 MHz |
//============================================================================= |
|
module PSGNoteGen(rst, clk, cnt, br, bg, bgn, ack, test, |
vt0, vt1, vt2, vt3, |
freq0, freq1, freq2, freq3, |
pw0, pw1, pw2, pw3, |
acc0, acc1, acc2, acc3, |
wave, sync, ringmod, o |
); |
input rst; |
input clk; |
input [7:0] cnt; |
input ack; |
input [11:0] wave; |
input [2:0] bgn; // bus grant number |
output [3:0] br; |
input [3:0] bg; |
input [3:0] test; |
input [4:0] vt0, vt1, vt2, vt3; |
input [15:0] freq0, freq1, freq2, freq3; |
input [11:0] pw0, pw1, pw2, pw3; |
input [3:0] sync; |
input [3:0] ringmod; |
// input pxacc25; |
output [23:0] acc0, acc1, acc2, acc3; // 1.023MHz / 2^ 24 = 0.06Hz resolution |
output [11:0] o; |
|
wire [15:0] freqx; |
wire [11:0] pwx; |
reg [23:0] pxacc; |
reg [23:0] acc; |
reg [11:0] outputT; |
reg [7:0] pxacc23x; |
reg [7:0] ibr; |
|
integer n; |
|
reg [23:0] accx [3:0]; |
reg [11:0] pacc [3:0]; |
wire [1:0] sel = cnt[1:0]; |
reg [11:0] outputW [3:0]; |
reg [22:0] lfsr [3:0]; |
|
assign br[0] = ibr[0] & ~bg[0]; |
assign br[1] = ibr[1] & ~bg[1]; |
assign br[2] = ibr[2] & ~bg[2]; |
assign br[3] = ibr[3] & ~bg[3]; |
|
wire [4:0] vtx; |
|
always @(sel) |
acc <= accx[sel]; |
|
|
mux4to1 #(16) u1 (.e(1'b1), .s(sel), .i0(freq0), .i1(freq1), .i2(freq2), .i3(freq3), .z(freqx) ); |
mux4to1 #(12) u2 (.e(1'b1), .s(sel), .i0(pw0), .i1(pw1), .i2(pw2), .i3(pw3), .z(pwx) ); |
mux4to1 #( 5) u3 (.e(1'b1), .s(sel), .i0(vt0), .i1(vt1), .i2(vt2), .i3(vt3), .z(vtx) ); |
|
|
wire [22:0] lfsrx = lfsr[sel]; |
wire [7:0] paccx = pacc[sel]; |
|
always @(sel) |
pxacc <= accx[sel-1]; |
wire pxacc23 = pxacc[23]; |
|
|
// for sync'ing |
always @(posedge clk) |
if (cnt < 8'd4) |
pxacc23x[sel] <= pxacc23; |
|
wire synca = ~pxacc23x[sel]&pxacc23&sync[sel]; |
|
|
// detect a transition on the wavetable address |
// previous address not equal to current address |
wire accTran = pacc[sel]!=acc[23:12]; |
|
// for wave table DMA |
// capture the previous address |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < 4; n = n + 1) |
pacc[n] <= 0; |
end |
else if (cnt < 8'd4) |
pacc[sel] <= acc[23:12]; |
|
|
// capture wave input |
// must be to who was granted the bus |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < 8'd4; n = n + 1) |
outputW[n] <= 0; |
end |
else if (ack) |
outputW[bgn] <= wave; |
|
|
// bus request control |
always @(posedge clk) |
if (rst) begin |
ibr <= 0; |
end |
else if (cnt < 8'd4) begin |
// check for an address transition and wave enabled |
// if so, request bus |
if (accTran & vtx[4]) |
ibr[sel] <= 1; |
// otherwise |
// turn off bus request for whoever it was granted |
else |
ibr[bgn] <= 0; |
end |
|
|
// Noise generator |
always @(posedge clk) |
if (cnt < 8'd4 && paccx[2] != acc[18]) |
lfsr[sel] <= {lfsrx[21:0],~(lfsrx[22]^lfsrx[17])}; |
|
|
// Harmonic synthesizer |
always @(posedge clk) |
if (rst) begin |
for (n = 0; n < 4; n = n + 1) |
accx[n] <= 0; |
end |
else if (cnt < 8'd4) begin |
if (~test[sel]) begin |
if (synca) |
accx[sel] <= 0; |
else |
accx[sel] <= acc + freqx; |
end |
else |
accx[sel] <= 0; |
end |
|
|
// Triangle wave, ring modulation |
wire msb = ringmod[sel] ? acc[23]^pxacc23 : acc[23]; |
always @(acc or msb) |
outputT <= msb ? ~acc[22:11] : acc[22:11]; |
|
// Other waveforms, ho-hum |
wire [11:0] outputP = {12{acc[23:12] < pwx}}; |
wire [11:0] outputS = acc[23:12]; |
wire [11:0] outputN = lfsrx[11:0]; |
|
wire [11:0] out; |
PSGNoteOutMux #(12) u4 (.s(vtx), .a(outputT), .b(outputS), .c(outputP), .d(outputN), .e(outputW[sel]), .o(out) ); |
assign o = out; |
|
assign acc0 = accx[0]; |
assign acc1 = accx[1]; |
assign acc2 = accx[2]; |
assign acc3 = accx[3]; |
|
endmodule |
|
/doc/gpl.txt
0,0 → 1,674
GNU GENERAL PUBLIC LICENSE |
Version 3, 29 June 2007 |
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
|
Preamble |
|
The GNU General Public License is a free, copyleft license for |
software and other kinds of works. |
|
The licenses for most software and other practical works are designed |
to take away your freedom to share and change the works. By contrast, |
the GNU General Public License is intended to guarantee your freedom to |
share and change all versions of a program--to make sure it remains free |
software for all its users. We, the Free Software Foundation, use the |
GNU General Public License for most of our software; it applies also to |
any other work released this way by its authors. You can apply it to |
your programs, too. |
|
When we speak of free software, we are referring to freedom, not |
price. Our General Public Licenses are designed to make sure that you |
have the freedom to distribute copies of free software (and charge for |
them if you wish), that you receive source code or can get it if you |
want it, that you can change the software or use pieces of it in new |
free programs, and that you know you can do these things. |
|
To protect your rights, we need to prevent others from denying you |
these rights or asking you to surrender the rights. Therefore, you have |
certain responsibilities if you distribute copies of the software, or if |
you modify it: responsibilities to respect the freedom of others. |
|
For example, if you distribute copies of such a program, whether |
gratis or for a fee, you must pass on to the recipients the same |
freedoms that you received. You must make sure that they, too, receive |
or can get the source code. And you must show them these terms so they |
know their rights. |
|
Developers that use the GNU GPL protect your rights with two steps: |
(1) assert copyright on the software, and (2) offer you this License |
giving you legal permission to copy, distribute and/or modify it. |
|
For the developers' and authors' protection, the GPL clearly explains |
that there is no warranty for this free software. For both users' and |
authors' sake, the GPL requires that modified versions be marked as |
changed, so that their problems will not be attributed erroneously to |
authors of previous versions. |
|
Some devices are designed to deny users access to install or run |
modified versions of the software inside them, although the manufacturer |
can do so. This is fundamentally incompatible with the aim of |
protecting users' freedom to change the software. The systematic |
pattern of such abuse occurs in the area of products for individuals to |
use, which is precisely where it is most unacceptable. Therefore, we |
have designed this version of the GPL to prohibit the practice for those |
products. If such problems arise substantially in other domains, we |
stand ready to extend this provision to those domains in future versions |
of the GPL, as needed to protect the freedom of users. |
|
Finally, every program is threatened constantly by software patents. |
States should not allow patents to restrict development and use of |
software on general-purpose computers, but in those that do, we wish to |
avoid the special danger that patents applied to a free program could |
make it effectively proprietary. To prevent this, the GPL assures that |
patents cannot be used to render the program non-free. |
|
The precise terms and conditions for copying, distribution and |
modification follow. |
|
TERMS AND CONDITIONS |
|
0. Definitions. |
|
"This License" refers to version 3 of the GNU General Public License. |
|
"Copyright" also means copyright-like laws that apply to other kinds of |
works, such as semiconductor masks. |
|
"The Program" refers to any copyrightable work licensed under this |
License. Each licensee is addressed as "you". "Licensees" and |
"recipients" may be individuals or organizations. |
|
To "modify" a work means to copy from or adapt all or part of the work |
in a fashion requiring copyright permission, other than the making of an |
exact copy. The resulting work is called a "modified version" of the |
earlier work or a work "based on" the earlier work. |
|
A "covered work" means either the unmodified Program or a work based |
on the Program. |
|
To "propagate" a work means to do anything with it that, without |
permission, would make you directly or secondarily liable for |
infringement under applicable copyright law, except executing it on a |
computer or modifying a private copy. Propagation includes copying, |
distribution (with or without modification), making available to the |
public, and in some countries other activities as well. |
|
To "convey" a work means any kind of propagation that enables other |
parties to make or receive copies. Mere interaction with a user through |
a computer network, with no transfer of a copy, is not conveying. |
|
An interactive user interface displays "Appropriate Legal Notices" |
to the extent that it includes a convenient and prominently visible |
feature that (1) displays an appropriate copyright notice, and (2) |
tells the user that there is no warranty for the work (except to the |
extent that warranties are provided), that licensees may convey the |
work under this License, and how to view a copy of this License. If |
the interface presents a list of user commands or options, such as a |
menu, a prominent item in the list meets this criterion. |
|
1. Source Code. |
|
The "source code" for a work means the preferred form of the work |
for making modifications to it. "Object code" means any non-source |
form of a work. |
|
A "Standard Interface" means an interface that either is an official |
standard defined by a recognized standards body, or, in the case of |
interfaces specified for a particular programming language, one that |
is widely used among developers working in that language. |
|
The "System Libraries" of an executable work include anything, other |
than the work as a whole, that (a) is included in the normal form of |
packaging a Major Component, but which is not part of that Major |
Component, and (b) serves only to enable use of the work with that |
Major Component, or to implement a Standard Interface for which an |
implementation is available to the public in source code form. A |
"Major Component", in this context, means a major essential component |
(kernel, window system, and so on) of the specific operating system |
(if any) on which the executable work runs, or a compiler used to |
produce the work, or an object code interpreter used to run it. |
|
The "Corresponding Source" for a work in object code form means all |
the source code needed to generate, install, and (for an executable |
work) run the object code and to modify the work, including scripts to |
control those activities. However, it does not include the work's |
System Libraries, or general-purpose tools or generally available free |
programs which are used unmodified in performing those activities but |
which are not part of the work. For example, Corresponding Source |
includes interface definition files associated with source files for |
the work, and the source code for shared libraries and dynamically |
linked subprograms that the work is specifically designed to require, |
such as by intimate data communication or control flow between those |
subprograms and other parts of the work. |
|
The Corresponding Source need not include anything that users |
can regenerate automatically from other parts of the Corresponding |
Source. |
|
The Corresponding Source for a work in source code form is that |
same work. |
|
2. Basic Permissions. |
|
All rights granted under this License are granted for the term of |
copyright on the Program, and are irrevocable provided the stated |
conditions are met. This License explicitly affirms your unlimited |
permission to run the unmodified Program. The output from running a |
covered work is covered by this License only if the output, given its |
content, constitutes a covered work. This License acknowledges your |
rights of fair use or other equivalent, as provided by copyright law. |
|
You may make, run and propagate covered works that you do not |
convey, without conditions so long as your license otherwise remains |
in force. You may convey covered works to others for the sole purpose |
of having them make modifications exclusively for you, or provide you |
with facilities for running those works, provided that you comply with |
the terms of this License in conveying all material for which you do |
not control copyright. Those thus making or running the covered works |
for you must do so exclusively on your behalf, under your direction |
and control, on terms that prohibit them from making any copies of |
your copyrighted material outside their relationship with you. |
|
Conveying under any other circumstances is permitted solely under |
the conditions stated below. Sublicensing is not allowed; section 10 |
makes it unnecessary. |
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|
No covered work shall be deemed part of an effective technological |
measure under any applicable law fulfilling obligations under article |
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
similar laws prohibiting or restricting circumvention of such |
measures. |
|
When you convey a covered work, you waive any legal power to forbid |
circumvention of technological measures to the extent such circumvention |
is effected by exercising rights under this License with respect to |
the covered work, and you disclaim any intention to limit operation or |
modification of the work as a means of enforcing, against the work's |
users, your or third parties' legal rights to forbid circumvention of |
technological measures. |
|
4. Conveying Verbatim Copies. |
|
You may convey verbatim copies of the Program's source code as you |
receive it, in any medium, provided that you conspicuously and |
appropriately publish on each copy an appropriate copyright notice; |
keep intact all notices stating that this License and any |
non-permissive terms added in accord with section 7 apply to the code; |
keep intact all notices of the absence of any warranty; and give all |
recipients a copy of this License along with the Program. |
|
You may charge any price or no price for each copy that you convey, |
and you may offer support or warranty protection for a fee. |
|
5. Conveying Modified Source Versions. |
|
You may convey a work based on the Program, or the modifications to |
produce it from the Program, in the form of source code under the |
terms of section 4, provided that you also meet all of these conditions: |
|
a) The work must carry prominent notices stating that you modified |
it, and giving a relevant date. |
|
b) The work must carry prominent notices stating that it is |
released under this License and any conditions added under section |
7. This requirement modifies the requirement in section 4 to |
"keep intact all notices". |
|
c) You must license the entire work, as a whole, under this |
License to anyone who comes into possession of a copy. This |
License will therefore apply, along with any applicable section 7 |
additional terms, to the whole of the work, and all its parts, |
regardless of how they are packaged. This License gives no |
permission to license the work in any other way, but it does not |
invalidate such permission if you have separately received it. |
|
d) If the work has interactive user interfaces, each must display |
Appropriate Legal Notices; however, if the Program has interactive |
interfaces that do not display Appropriate Legal Notices, your |
work need not make them do so. |
|
A compilation of a covered work with other separate and independent |
works, which are not by their nature extensions of the covered work, |
and which are not combined with it such as to form a larger program, |
in or on a volume of a storage or distribution medium, is called an |
"aggregate" if the compilation and its resulting copyright are not |
used to limit the access or legal rights of the compilation's users |
beyond what the individual works permit. Inclusion of a covered work |
in an aggregate does not cause this License to apply to the other |
parts of the aggregate. |
|
6. Conveying Non-Source Forms. |
|
You may convey a covered work in object code form under the terms |
of sections 4 and 5, provided that you also convey the |
machine-readable Corresponding Source under the terms of this License, |
in one of these ways: |
|
a) Convey the object code in, or embodied in, a physical product |
(including a physical distribution medium), accompanied by the |
Corresponding Source fixed on a durable physical medium |
customarily used for software interchange. |
|
b) Convey the object code in, or embodied in, a physical product |
(including a physical distribution medium), accompanied by a |
written offer, valid for at least three years and valid for as |
long as you offer spare parts or customer support for that product |
model, to give anyone who possesses the object code either (1) a |
copy of the Corresponding Source for all the software in the |
product that is covered by this License, on a durable physical |
medium customarily used for software interchange, for a price no |
more than your reasonable cost of physically performing this |
conveying of source, or (2) access to copy the |
Corresponding Source from a network server at no charge. |
|
c) Convey individual copies of the object code with a copy of the |
written offer to provide the Corresponding Source. This |
alternative is allowed only occasionally and noncommercially, and |
only if you received the object code with such an offer, in accord |
with subsection 6b. |
|
d) Convey the object code by offering access from a designated |
place (gratis or for a charge), and offer equivalent access to the |
Corresponding Source in the same way through the same place at no |
further charge. You need not require recipients to copy the |
Corresponding Source along with the object code. If the place to |
copy the object code is a network server, the Corresponding Source |
may be on a different server (operated by you or a third party) |
that supports equivalent copying facilities, provided you maintain |
clear directions next to the object code saying where to find the |
Corresponding Source. Regardless of what server hosts the |
Corresponding Source, you remain obligated to ensure that it is |
available for as long as needed to satisfy these requirements. |
|
e) Convey the object code using peer-to-peer transmission, provided |
you inform other peers where the object code and Corresponding |
Source of the work are being offered to the general public at no |
charge under subsection 6d. |
|
A separable portion of the object code, whose source code is excluded |
from the Corresponding Source as a System Library, need not be |
included in conveying the object code work. |
|
A "User Product" is either (1) a "consumer product", which means any |
tangible personal property which is normally used for personal, family, |
or household purposes, or (2) anything designed or sold for incorporation |
into a dwelling. In determining whether a product is a consumer product, |
doubtful cases shall be resolved in favor of coverage. For a particular |
product received by a particular user, "normally used" refers to a |
typical or common use of that class of product, regardless of the status |
of the particular user or of the way in which the particular user |
actually uses, or expects or is expected to use, the product. A product |
is a consumer product regardless of whether the product has substantial |
commercial, industrial or non-consumer uses, unless such uses represent |
the only significant mode of use of the product. |
|
"Installation Information" for a User Product means any methods, |
procedures, authorization keys, or other information required to install |
and execute modified versions of a covered work in that User Product from |
a modified version of its Corresponding Source. The information must |
suffice to ensure that the continued functioning of the modified object |
code is in no case prevented or interfered with solely because |
modification has been made. |
|
If you convey an object code work under this section in, or with, or |
specifically for use in, a User Product, and the conveying occurs as |
part of a transaction in which the right of possession and use of the |
User Product is transferred to the recipient in perpetuity or for a |
fixed term (regardless of how the transaction is characterized), the |
Corresponding Source conveyed under this section must be accompanied |
by the Installation Information. But this requirement does not apply |
if neither you nor any third party retains the ability to install |
modified object code on the User Product (for example, the work has |
been installed in ROM). |
|
The requirement to provide Installation Information does not include a |
requirement to continue to provide support service, warranty, or updates |
for a work that has been modified or installed by the recipient, or for |
the User Product in which it has been modified or installed. Access to a |
network may be denied when the modification itself materially and |
adversely affects the operation of the network or violates the rules and |
protocols for communication across the network. |
|
Corresponding Source conveyed, and Installation Information provided, |
in accord with this section must be in a format that is publicly |
documented (and with an implementation available to the public in |
source code form), and must require no special password or key for |
unpacking, reading or copying. |
|
7. Additional Terms. |
|
"Additional permissions" are terms that supplement the terms of this |
License by making exceptions from one or more of its conditions. |
Additional permissions that are applicable to the entire Program shall |
be treated as though they were included in this License, to the extent |
that they are valid under applicable law. If additional permissions |
apply only to part of the Program, that part may be used separately |
under those permissions, but the entire Program remains governed by |
this License without regard to the additional permissions. |
|
When you convey a copy of a covered work, you may at your option |
remove any additional permissions from that copy, or from any part of |
it. (Additional permissions may be written to require their own |
removal in certain cases when you modify the work.) You may place |
additional permissions on material, added by you to a covered work, |
for which you have or can give appropriate copyright permission. |
|
Notwithstanding any other provision of this License, for material you |
add to a covered work, you may (if authorized by the copyright holders of |
that material) supplement the terms of this License with terms: |
|
a) Disclaiming warranty or limiting liability differently from the |
terms of sections 15 and 16 of this License; or |
|
b) Requiring preservation of specified reasonable legal notices or |
author attributions in that material or in the Appropriate Legal |
Notices displayed by works containing it; or |
|
c) Prohibiting misrepresentation of the origin of that material, or |
requiring that modified versions of such material be marked in |
reasonable ways as different from the original version; or |
|
d) Limiting the use for publicity purposes of names of licensors or |
authors of the material; or |
|
e) Declining to grant rights under trademark law for use of some |
trade names, trademarks, or service marks; or |
|
f) Requiring indemnification of licensors and authors of that |
material by anyone who conveys the material (or modified versions of |
it) with contractual assumptions of liability to the recipient, for |
any liability that these contractual assumptions directly impose on |
those licensors and authors. |
|
All other non-permissive additional terms are considered "further |
restrictions" within the meaning of section 10. If the Program as you |
received it, or any part of it, contains a notice stating that it is |
governed by this License along with a term that is a further |
restriction, you may remove that term. If a license document contains |
a further restriction but permits relicensing or conveying under this |
License, you may add to a covered work material governed by the terms |
of that license document, provided that the further restriction does |
not survive such relicensing or conveying. |
|
If you add terms to a covered work in accord with this section, you |
must place, in the relevant source files, a statement of the |
additional terms that apply to those files, or a notice indicating |
where to find the applicable terms. |
|
Additional terms, permissive or non-permissive, may be stated in the |
form of a separately written license, or stated as exceptions; |
the above requirements apply either way. |
|
8. Termination. |
|
You may not propagate or modify a covered work except as expressly |
provided under this License. Any attempt otherwise to propagate or |
modify it is void, and will automatically terminate your rights under |
this License (including any patent licenses granted under the third |
paragraph of section 11). |
|
However, if you cease all violation of this License, then your |
license from a particular copyright holder is reinstated (a) |
provisionally, unless and until the copyright holder explicitly and |
finally terminates your license, and (b) permanently, if the copyright |
holder fails to notify you of the violation by some reasonable means |
prior to 60 days after the cessation. |
|
Moreover, your license from a particular copyright holder is |
reinstated permanently if the copyright holder notifies you of the |
violation by some reasonable means, this is the first time you have |
received notice of violation of this License (for any work) from that |
copyright holder, and you cure the violation prior to 30 days after |
your receipt of the notice. |
|
Termination of your rights under this section does not terminate the |
licenses of parties who have received copies or rights from you under |
this License. If your rights have been terminated and not permanently |
reinstated, you do not qualify to receive new licenses for the same |
material under section 10. |
|
9. Acceptance Not Required for Having Copies. |
|
You are not required to accept this License in order to receive or |
run a copy of the Program. Ancillary propagation of a covered work |
occurring solely as a consequence of using peer-to-peer transmission |
to receive a copy likewise does not require acceptance. However, |
nothing other than this License grants you permission to propagate or |
modify any covered work. These actions infringe copyright if you do |
not accept this License. Therefore, by modifying or propagating a |
covered work, you indicate your acceptance of this License to do so. |
|
10. Automatic Licensing of Downstream Recipients. |
|
Each time you convey a covered work, the recipient automatically |
receives a license from the original licensors, to run, modify and |
propagate that work, subject to this License. You are not responsible |
for enforcing compliance by third parties with this License. |
|
An "entity transaction" is a transaction transferring control of an |
organization, or substantially all assets of one, or subdividing an |
organization, or merging organizations. If propagation of a covered |
work results from an entity transaction, each party to that |
transaction who receives a copy of the work also receives whatever |
licenses to the work the party's predecessor in interest had or could |
give under the previous paragraph, plus a right to possession of the |
Corresponding Source of the work from the predecessor in interest, if |
the predecessor has it or can get it with reasonable efforts. |
|
You may not impose any further restrictions on the exercise of the |
rights granted or affirmed under this License. For example, you may |
not impose a license fee, royalty, or other charge for exercise of |
rights granted under this License, and you may not initiate litigation |
(including a cross-claim or counterclaim in a lawsuit) alleging that |
any patent claim is infringed by making, using, selling, offering for |
sale, or importing the Program or any portion of it. |
|
11. Patents. |
|
A "contributor" is a copyright holder who authorizes use under this |
License of the Program or a work on which the Program is based. The |
work thus licensed is called the contributor's "contributor version". |
|
A contributor's "essential patent claims" are all patent claims |
owned or controlled by the contributor, whether already acquired or |
hereafter acquired, that would be infringed by some manner, permitted |
by this License, of making, using, or selling its contributor version, |
but do not include claims that would be infringed only as a |
consequence of further modification of the contributor version. For |
purposes of this definition, "control" includes the right to grant |
patent sublicenses in a manner consistent with the requirements of |
this License. |
|
Each contributor grants you a non-exclusive, worldwide, royalty-free |
patent license under the contributor's essential patent claims, to |
make, use, sell, offer for sale, import and otherwise run, modify and |
propagate the contents of its contributor version. |
|
In the following three paragraphs, a "patent license" is any express |
agreement or commitment, however denominated, not to enforce a patent |
(such as an express permission to practice a patent or covenant not to |
sue for patent infringement). To "grant" such a patent license to a |
party means to make such an agreement or commitment not to enforce a |
patent against the party. |
|
If you convey a covered work, knowingly relying on a patent license, |
and the Corresponding Source of the work is not available for anyone |
to copy, free of charge and under the terms of this License, through a |
publicly available network server or other readily accessible means, |
then you must either (1) cause the Corresponding Source to be so |
available, or (2) arrange to deprive yourself of the benefit of the |
patent license for this particular work, or (3) arrange, in a manner |
consistent with the requirements of this License, to extend the patent |
license to downstream recipients. "Knowingly relying" means you have |
actual knowledge that, but for the patent license, your conveying the |
covered work in a country, or your recipient's use of the covered work |
in a country, would infringe one or more identifiable patents in that |
country that you have reason to believe are valid. |
|
If, pursuant to or in connection with a single transaction or |
arrangement, you convey, or propagate by procuring conveyance of, a |
covered work, and grant a patent license to some of the parties |
receiving the covered work authorizing them to use, propagate, modify |
or convey a specific copy of the covered work, then the patent license |
you grant is automatically extended to all recipients of the covered |
work and works based on it. |
|
A patent license is "discriminatory" if it does not include within |
the scope of its coverage, prohibits the exercise of, or is |
conditioned on the non-exercise of one or more of the rights that are |
specifically granted under this License. You may not convey a covered |
work if you are a party to an arrangement with a third party that is |
in the business of distributing software, under which you make payment |
to the third party based on the extent of your activity of conveying |
the work, and under which the third party grants, to any of the |
parties who would receive the covered work from you, a discriminatory |
patent license (a) in connection with copies of the covered work |
conveyed by you (or copies made from those copies), or (b) primarily |
for and in connection with specific products or compilations that |
contain the covered work, unless you entered into that arrangement, |
or that patent license was granted, prior to 28 March 2007. |
|
Nothing in this License shall be construed as excluding or limiting |
any implied license or other defenses to infringement that may |
otherwise be available to you under applicable patent law. |
|
12. No Surrender of Others' Freedom. |
|
If conditions are imposed on you (whether by court order, agreement or |
otherwise) that contradict the conditions of this License, they do not |
excuse you from the conditions of this License. If you cannot convey a |
covered work so as to satisfy simultaneously your obligations under this |
License and any other pertinent obligations, then as a consequence you may |
not convey it at all. For example, if you agree to terms that obligate you |
to collect a royalty for further conveying from those to whom you convey |
the Program, the only way you could satisfy both those terms and this |
License would be to refrain entirely from conveying the Program. |
|
13. Use with the GNU Affero General Public License. |
|
Notwithstanding any other provision of this License, you have |
permission to link or combine any covered work with a work licensed |
under version 3 of the GNU Affero General Public License into a single |
combined work, and to convey the resulting work. The terms of this |
License will continue to apply to the part which is the covered work, |
but the special requirements of the GNU Affero General Public License, |
section 13, concerning interaction through a network will apply to the |
combination as such. |
|
14. Revised Versions of this License. |
|
The Free Software Foundation may publish revised and/or new versions of |
the GNU General Public License from time to time. Such new versions will |
be similar in spirit to the present version, but may differ in detail to |
address new problems or concerns. |
|
Each version is given a distinguishing version number. If the |
Program specifies that a certain numbered version of the GNU General |
Public License "or any later version" applies to it, you have the |
option of following the terms and conditions either of that numbered |
version or of any later version published by the Free Software |
Foundation. If the Program does not specify a version number of the |
GNU General Public License, you may choose any version ever published |
by the Free Software Foundation. |
|
If the Program specifies that a proxy can decide which future |
versions of the GNU General Public License can be used, that proxy's |
public statement of acceptance of a version permanently authorizes you |
to choose that version for the Program. |
|
Later license versions may give you additional or different |
permissions. However, no additional obligations are imposed on any |
author or copyright holder as a result of your choosing to follow a |
later version. |
|
15. Disclaimer of Warranty. |
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY |
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT |
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY |
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM |
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF |
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|
16. Limitation of Liability. |
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY |
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF |
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD |
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), |
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
SUCH DAMAGES. |
|
17. Interpretation of Sections 15 and 16. |
|
If the disclaimer of warranty and limitation of liability provided |
above cannot be given local legal effect according to their terms, |
reviewing courts shall apply local law that most closely approximates |
an absolute waiver of all civil liability in connection with the |
Program, unless a warranty or assumption of liability accompanies a |
copy of the Program in return for a fee. |
|
END OF TERMS AND CONDITIONS |
|
How to Apply These Terms to Your New Programs |
|
If you develop a new program, and you want it to be of the greatest |
possible use to the public, the best way to achieve this is to make it |
free software which everyone can redistribute and change under these terms. |
|
To do so, attach the following notices to the program. It is safest |
to attach them to the start of each source file to most effectively |
state the exclusion of warranty; and each file should have at least |
the "copyright" line and a pointer to where the full notice is found. |
|
<one line to give the program's name and a brief idea of what it does.> |
Copyright (C) <year> <name of author> |
|
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 3 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, see <http://www.gnu.org/licenses/>. |
|
Also add information on how to contact you by electronic and paper mail. |
|
If the program does terminal interaction, make it output a short |
notice like this when it starts in an interactive mode: |
|
<program> Copyright (C) <year> <name of author> |
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
This is free software, and you are welcome to redistribute it |
under certain conditions; type `show c' for details. |
|
The hypothetical commands `show w' and `show c' should show the appropriate |
parts of the General Public License. Of course, your program's commands |
might be different; for a GUI interface, you would use an "about box". |
|
You should also get your employer (if you work as a programmer) or school, |
if any, to sign a "copyright disclaimer" for the program, if necessary. |
For more information on this, and how to apply and follow the GNU GPL, see |
<http://www.gnu.org/licenses/>. |
|
The GNU General Public License does not permit incorporating your program |
into proprietary programs. If your program is a subroutine library, you |
may consider it more useful to permit linking proprietary applications with |
the library. If this is what you want to do, use the GNU Lesser General |
Public License instead of this License. But first, please read |
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
/doc/AC97 Controller.docx
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
doc/AC97 Controller.docx
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: doc/PSGBlock.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: doc/PSGBlock.gif
===================================================================
--- doc/PSGBlock.gif (nonexistent)
+++ doc/PSGBlock.gif (revision 2)
doc/PSGBlock.gif
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: doc/lgpl.txt
===================================================================
--- doc/lgpl.txt (nonexistent)
+++ doc/lgpl.txt (revision 2)
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
Index: doc/PSG16.docx
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: doc/PSG16.docx
===================================================================
--- doc/PSG16.docx (nonexistent)
+++ doc/PSG16.docx (revision 2)
doc/PSG16.docx
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: doc/PSG.xls
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: doc/PSG.xls
===================================================================
--- doc/PSG.xls (nonexistent)
+++ doc/PSG.xls (revision 2)
doc/PSG.xls
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: doc/~$PSG16.docx
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: doc/~$PSG16.docx
===================================================================
--- doc/~$PSG16.docx (nonexistent)
+++ doc/~$PSG16.docx (revision 2)
doc/~$PSG16.docx
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: software/code snippets/SetupAC97.asm
===================================================================
--- software/code snippets/SetupAC97.asm (nonexistent)
+++ software/code snippets/SetupAC97.asm (revision 2)
@@ -0,0 +1,36 @@
+AC97 EQU 0xFFFF_FFFF_FFDC_1000
+;--------------------------------------------------------------------------
+; Setup the AC97/LM4550 audio controller. Check keyboard for a CTRL-C
+; interrupt which may be necessary if the audio controller isn't
+; responding.
+;--------------------------------------------------------------------------
+;
+SetupAC97:
+ subui sp,sp,#16
+ sm [sp],r1/lr
+sac974:
+ sc r0,AC97+0x26 ; trigger a read of register 26 (status reg)
+sac971: ; wait for status to register 0xF (all ready)
+ call KeybdGetChar ; see if we needed to CTRL-C
+ beqi r1,#CTRLC,sac973
+ lc r1,AC97+0x68 ; wait for dirty bit to clear
+ bne r1,r0,sac971
+ lc r1,AC97+0x26 ; check status at reg h26, wait for
+ andi r1,r1,#0x0F ; analogue to be ready
+ bnei r1,#0x0F,sac974
+sac973:
+ sc r0,AC97+2 ; master volume, 0db attenuation, mute off
+ sc r0,AC97+4 ; headphone volume, 0db attenuation, mute off
+ sc r0,AC97+0x18 ; PCM gain (mixer) mute off, no attenuation
+ sc r0,AC97+0x0A ; mute PC beep
+ setlo r1,#0x8000 ; bypass 3D sound
+ sc r1,AC97+0x20
+sac972:
+ call KeybdGetChar
+ beqi r1,#CTRLC,sac975
+ lc r1,AC97+0x68 ; wait for dirty bits to clear
+ bne r1,r0,sac972 ; wait a while for the settings to take effect
+sac975:
+ lm [sp],r1/lr
+ addui sp,sp,#16
+ ret
Index: software/code snippets/Beep.asm
===================================================================
--- software/code snippets/Beep.asm (nonexistent)
+++ software/code snippets/Beep.asm (revision 2)
@@ -0,0 +1,38 @@
+PSG EQU 0xFFFF_FFFF_FFD5_0000
+PSGFREQ0 EQU 0xFFFF_FFFF_FFD5_0000
+PSGPW0 EQU 0xFFFF_FFFF_FFD5_0002
+PSGCTRL0 EQU 0xFFFF_FFFF_FFD5_0004
+PSGADSR0 EQU 0xFFFF_FFFF_FFD5_0006
+
+;--------------------------------------------------------------------------
+; Sound a 800 Hz beep
+;--------------------------------------------------------------------------
+;
+Beep:
+ subui sp,sp,#16
+ sm [sp],r1/lr
+ ori r1,r0,#15 ; master volume to max
+ sc r1,PSG+128
+ ori r1,r0,#13422 ; 800Hz
+ sc r1,PSGFREQ0
+ ; decay (16.384 ms)2
+ ; attack (8.192 ms)1
+ ; release (1.024 s)A
+ ; sustain level C
+ setlo r1,#0xCA12
+ sc r1,PSGADSR0
+ ori r1,r0,#0x1104 ; gate, output enable, triangle waveform
+ sc r1,PSGCTRL0
+ ori r1,r0,#25000000 ; delay about 1s
+beep1:
+ loop r1,beep1
+ ori r1,r0,#0x0104 ; gate off, output enable, triangle waveform
+ sc r1,PSGCTRL0
+ ori r1,r0,#25000000 ; delay about 1s
+beep2:
+ loop r1,beep2
+ ori r1,r0,#0x0000 ; gate off, output enable off, no waveform
+ sc r1,PSGCTRL0
+ lm [sp],r1/lr
+ ret #16
+