URL
https://opencores.org/ocsvn/sqmusic/sqmusic/trunk
Subversion Repositories sqmusic
Compare Revisions
- This comparison shows the changes necessary to convert path
/sqmusic/trunk
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/1942/1942.v
17,12 → 17,8
`timescale 1ns / 1ps |
|
module sound1942; |
wire [7:0]cpu_in, cpu_out; |
wire [15:0]adr; |
wire m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n; |
wire bus_error; |
// inputs to Z80 |
reg reset_n, clk, wait_n, int_n, nmi_n, busrq_n, sound_clk; |
reg reset_n, clk, int_n, sound_clk; |
|
initial begin |
//$dumpfile("dump.lxt"); |
32,12 → 28,10
// $shm_open("1942.shm"); |
// $shm_probe( sound1942, "ACTFS" ); |
reset_n=0; |
nmi_n=1; |
wait_n=1; |
#1500 reset_n=1; |
// change finish time depending on song |
// #400e6 $finish; |
#10e9 $finish; |
//#4e6 $finish; |
#5e9 $finish; |
end |
|
always begin // main clock |
60,34 → 54,42
#(int_low_time) int_n=1; |
end |
end |
|
|
tv80n cpu( //outputs |
.m1_n(m1_n), .mreq_n(mreq_n), .iorq_n(iorq_n), .rd_n(rd_n), .wr_n(wr_n), |
.rfsh_n(rfsh_n), .halt_n(halt_n), .busak_n(busak_n), .A(adr), .do(cpu_out), |
// Inputs |
.reset_n(reset_n), .clk(clk), .wait_n(wait_n), |
.int_n(int_n), .nmi_n(nmi_n), .busrq_n(busrq_n), .di(cpu_in) ); |
|
MAP map( .adr(adr), .din(cpu_out), .dout(cpu_in), .clk(clk), |
.sound_clk( sound_clk ), .wr_n(wr_n), .rd_n(rd_n), |
.bus_error(bus_error), .reset_n(reset_n) ); |
|
|
|
always #22676 $display("%d", amp0_y+amp1_y ); // 44.1kHz sample |
|
wire [3:0] ay0_a, ay0_b, ay0_c, ay1_a, ay1_b, ay1_c; |
computer_1942 #(0) game( .clk(clk), .sound_clk(sound_clk), |
.int_n(int_n), .reset_n(reset_n), |
.ay0_a(ay0_a), .ay0_b(ay0_b), .ay0_c(ay0_c), |
.ay1_a(ay1_a), .ay1_b(ay1_b), .ay1_c(ay1_c) ); |
// sound amplifier: |
wire [15:0] amp0_y, amp1_y; |
SQM_AMP amp0( .A(ay0_a), .B(ay0_b), .C(ay0_c), .Y( amp0_y )); |
SQM_AMP amp1( .A(ay1_a), .B(ay1_b), .C(ay1_c), .Y( amp1_y )); |
endmodule |
|
///////////////////////////////////////////////////// |
module MAP( |
input [15:0] adr, |
input [7:0] din, |
output [7:0] dout, |
module computer_1942 |
#(parameter dump_regs=0) // set to 1 to dump sqmusic registers |
( |
input clk, |
input sound_clk, |
input rd_n, |
input wr_n, |
input reset_n, |
output bus_error ); |
input int_n, |
output [3:0] ay0_a, |
output [3:0] ay0_b, |
output [3:0] ay0_c, |
output [3:0] ay1_a, |
output [3:0] ay1_b, |
output [3:0] ay1_c |
); |
reg wait_n, nmi_n, busrq_n; |
|
wire [7:0]cpu_in, cpu_out; |
wire [15:0]adr; |
wire m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n; |
wire bus_error; |
|
|
wire [3:0] ay0_a, ay0_b, ay0_c, ay1_a, ay1_b, ay1_c; |
wire [15:0] amp0_y, amp1_y; |
100,13 → 102,25
wire ay_1_enable = adr==16'hC000 || adr==16'hC001 ? 1:0; |
assign bus_error = ~ram_enable & ~rom_enable & ~latch_enable & |
~ay_0_enable & ~ay_1_enable; |
assign dout=ram_out | rom_out | latch_out; |
assign cpu_in=ram_out | rom_out | latch_out; |
/* |
always @(negedge rd_n) |
if( !rd_n && adr==8'h38 ) |
$display("IRQ processing started @ %t us",$time/1e6); |
*/ |
RAM ram(.adr(adr[10:0]), .din(din), .dout(ram_out), .enable( ram_enable ), |
initial begin |
nmi_n=1; |
wait_n=1; |
end |
|
tv80n cpu( //outputs |
.m1_n(m1_n), .mreq_n(mreq_n), .iorq_n(iorq_n), .rd_n(rd_n), .wr_n(wr_n), |
.rfsh_n(rfsh_n), .halt_n(halt_n), .busak_n(busak_n), .A(adr), .do(cpu_out), |
// Inputs |
.reset_n(reset_n), .clk(clk), .wait_n(wait_n), |
.int_n(int_n), .nmi_n(nmi_n), .busrq_n(busrq_n), .di(cpu_in) ); |
|
RAM ram(.adr(adr[10:0]), .din(cpu_out), .dout(ram_out), .enable( ram_enable ), |
.clk(clk), .wr_n(wr_n), .rd_n(rd_n) ); |
ROM rom(.adr(adr[13:0]), .data(rom_out), .enable(rom_enable), |
.rd_n(rd_n), .clk(clk)); |
115,18 → 129,12
|
// fake_ay ay_0( .adr(adr[0]), .din(din), .clk(clk), .wr_n(~ay_0_enable|wr_n) ); |
|
AY_3_8910_capcom ay_0( .reset_n(reset_n), .clk(clk), .sound_clk(sound_clk), |
.din(din), .adr(adr[0]), .wr_n(wr_n), .cs_n(~ay_0_enable), |
AY_3_8910_capcom #(dump_regs,0) ay_0( .reset_n(reset_n), .clk(clk), .sound_clk(sound_clk), |
.din(cpu_out), .adr(adr[0]), .wr_n(wr_n), .cs_n(~ay_0_enable), |
.A(ay0_a), .B(ay0_b), .C(ay0_c) ); |
AY_3_8910_capcom ay_1( .reset_n(reset_n), .clk(clk), .sound_clk(sound_clk), |
.din(din), .adr(adr[0]), .wr_n(wr_n), .cs_n(~ay_1_enable), |
AY_3_8910_capcom #(dump_regs,1) ay_1( .reset_n(reset_n), .clk(clk), .sound_clk(sound_clk), |
.din(cpu_out), .adr(adr[0]), .wr_n(wr_n), .cs_n(~ay_1_enable), |
.A(ay1_a), .B(ay1_b), .C(ay1_c) ); |
|
SQM_AMP amp0( .A(ay0_a), .B(ay0_b), .C(ay0_c), .Y( amp0_y )); |
SQM_AMP amp1( .A(ay1_a), .B(ay1_b), .C(ay1_c), .Y( amp1_y )); |
|
always #22676 $display("%d", amp0_y+amp1_y ); // 44.1kHz sample |
// initial $dumpvars(0,ym2203_0); |
endmodule |
|
////////////////////////////////////////////////////////// |
/1942/log2wav.cc
18,37 → 18,74
#include <string.h> |
#include <stdlib.h> |
#include <assert.h> |
#include <string.h> |
#include <string> |
|
using namespace std; |
|
class Args { |
public: |
int skip; |
string filename; |
string outputfile; |
Args( int argc, char *argv[]) : skip(0), outputfile("out.wav") { |
int k=1; |
bool filename_known=false; |
while( k < argc ) { |
if( strcmp(argv[k],"-l")==0 ) { |
k++; |
if( k >= argc ) throw "Expected number of lines to skip after -l"; |
skip = atoi( argv[k] ); |
cout << skip << " lines will be skipped\n"; |
k++; |
continue; |
} |
if( strcmp(argv[k],"-o")==0 ) { |
k++; |
if( k >= argc ) throw "Expected output file name after -o"; |
outputfile = argv[k]; |
k++; |
continue; |
} |
if( filename_known ) { |
cout << "Unknown parameter " << argv[k] << "\n"; |
throw "Incorrect command line"; |
} |
filename = argv[k]; |
filename_known = true; |
k++; |
} |
if( filename=="-" ) filename=string("/dev/stdin"); |
} |
}; |
|
int main(int argc, char *argv[]) { |
try { |
ifstream fin; |
if( argc == 2) |
fin.open(argv[1]); |
else |
fin.open("/dev/stdin"); |
ofstream fout("out.wav"); |
if( fin.bad() ) throw "Cannot open input file"; |
if( fout.bad() ) throw "Cannot open output file"; |
Args ar( argc, argv ); |
cout << "Input file " << ar.filename << "\n"; |
fin.open(ar.filename.c_str()); |
ofstream fout(ar.outputfile.c_str()); |
if( fin.bad() || fin.fail() ) throw "Cannot open input file"; |
if( fout.bad() || fout.fail() ) throw "Cannot open output file"; |
assert( sizeof(short int)==2 ); |
char buffer[1024]; |
int data=0; |
|
|
// depending on the simulator the following "while" |
// section might no be needed or modified |
// It just skips simulator output until the real data |
// starts to come out |
while( !fin.eof() ) { |
// starts to come out |
for( int k=0; k<ar.skip && !fin.eof(); k++ ) { |
fin.getline( buffer, sizeof(buffer) ); |
if( strcmp(buffer,"ncsim> run" )==0) break; |
//if( strcmp(buffer,"ncsim> run" )==0) break; |
} |
|
if( fin.eof() ) throw "Data not found"; |
fout.seekp(44); |
while( !fin.eof() ) { |
while( !fin.eof() && !fin.bad() && !fin.fail() ) { |
short int value; |
fin.getline( buffer, sizeof(buffer) ); |
|
if( buffer[0]=='S' ) break; // reached line "Simulation complete" |
value = atoi( buffer ); |
fout.write( (char*) &value, sizeof(value) ); |
/1942/readme
5,6 → 5,9
2. Compile and run "dump.cc" program to convert the binary file to hexadecimal format |
3. Place file in ../rom folder (see 1942.v file for details on location) |
4. Run verilog simulation from 1942 folder using the "gather" file |
|
$ iverilog -s sound1942 -f gather -o sound1942 && vvp sound1942 > sim.log |
|
5. Pass the output of the simulation through "log2wav.cc", either using a pipe or storing it on a file. Check that the data dump is caught correctly by log2wav as some simulators will add extra information at the beginning of the file |
|
Other: |
/sqm/sqm_pwm.v
0,0 → 1,158
/* |
SQmusic |
logarithmic PWM controller to use with SQMUSIC |
Version 0.1, tested on simulation only with Capcom's 1942 |
|
(c) Jose Tejada Gomez, 11th May 2013 |
You can use this file following the GNU GENERAL PUBLIC LICENSE version 3 |
Read the details of the license in: |
http://www.gnu.org/licenses/gpl.txt |
|
Send comments to: jose.tejada@ieee.org |
|
*/ |
`timescale 1ns / 1ps |
module SQM_PWM( |
input clk, // VHF clock (>33 MHz) |
input reset_n, |
input [3:0]A, input [3:0]B, input [3:0]C, // input channels |
output Y |
); |
|
|
SQM_PWM_1 apwm( .clk(clk), .reset_n(reset_n), .din(A), .pwm(y_a) ); |
SQM_PWM_1 bpwm( .clk(clk), .reset_n(reset_n), .din(B), .pwm(y_b) ); |
SQM_PWM_1 cpwm( .clk(clk), .reset_n(reset_n), .din(C), .pwm(y_c) ); |
|
assign Y=y_a | y_b | y_c; |
endmodule |
|
//////////////////////////////////////////////////// |
// 1 channel only |
module SQM_PWM_1( |
input clk, // VHF clock (>33 MHz) |
input reset_n, |
input [3:0]din, |
output reg pwm |
); |
|
reg [7:0] count, last0, last1; |
wire [7:0]rep0, rep1; |
|
SQM_PWM_LOG dec( .din(din), .rep0(rep0), .rep1(rep1), .zero(zero) ); |
|
always @(posedge clk or negedge reset_n) begin |
if( !reset_n ) begin |
count=0; |
last0=0; |
last1=1; |
end |
else |
if( zero ) begin |
pwm=0; |
count=0; |
end |
else if( last0!=rep0 || last1!=rep1 ) begin |
last0 <= rep0; |
last1 <= rep1; |
count = 0; |
pwm=0; |
end |
else if( last0==1 && last1==1 ) begin |
pwm=clk; |
count=0; |
end |
else begin |
if( pwm && count==last1-1 ) begin |
count=0; |
pwm=0; |
end |
else if( !pwm && count==last0-1 ) begin |
count=0; |
pwm=1; |
end |
else begin |
count<=count+1; |
pwm<=pwm; |
end |
end |
end |
endmodule |
|
module SQM_PWM_LOG( |
input [3:0]din, |
output reg [7:0] rep0, // "L" repetition |
output reg [7:0] rep1, // "H" repetition |
output zero |
); |
|
assign zero = din==0; |
|
always @(din) |
case (din) |
1: begin |
rep0=64; |
rep1=1; |
end |
2: begin |
rep0=61; |
rep1=1; |
end |
3: begin |
rep0=32; |
rep1=1; |
end |
4: begin |
rep0=61; |
rep1=2; |
end |
5: begin |
rep0=16; |
rep1=1; |
end |
6: begin |
rep0=61; |
rep1=4; |
end |
7: begin |
rep0=8; |
rep1=1; |
end |
8: begin |
rep0=61; |
rep1=8; |
end |
9: begin |
rep0=61; |
rep1=16; |
end |
10: begin |
rep0=61; |
rep1=8; |
end |
11: begin |
rep0=2; |
rep1=1; |
end |
12: begin |
rep0=61; |
rep1=32; |
end |
13: begin |
rep0=1; |
rep1=1; |
end |
14: begin |
rep0=61; |
rep1=64; |
end |
15: begin |
rep0=1; |
rep1=1; |
end |
default: begin |
rep0=1; |
rep1=1; |
end |
endcase |
endmodule |
/sqm/sqmusic.v
17,7 → 17,9
provides a 2-byte memory map as expected by Capcom games |
*/ |
`timescale 1ns / 1ps |
module AY_3_8910_capcom( |
module AY_3_8910_capcom |
#( parameter dump_writes=0, parameter id=0 ) |
( |
input reset_n, |
input clk, // CPU clock |
input sound_clk, // normally slower than the CPU clock |
57,17 → 59,19
end |
end |
|
SQMUSIC core( .reset_n(reset_n), .clk(sound_clk), .data_in(latches[1]), |
SQMUSIC #(dump_writes, id) core( .reset_n(reset_n), .clk(sound_clk), .data_in(latches[1]), |
.adr( latches[0][3:0] ), .rd(1'b0), .wr(core_wr), .A(A), .B(B), .C(C) ); |
endmodule |
|
/* The AY core does |
*/ |
module SQMUSIC( // pins are not multiplexed |
module SQMUSIC |
#( parameter dump_writes=0, parameter id=0 ) // set to 1 to dump register writes |
( // note that input ports are not multiplexed |
input reset_n, |
input clk, |
input [7:0] data_in, |
output reg [7:0] data_out, // read functionality not implemented yet |
output reg [7:0] data_out, |
input [3:0] adr, |
input rd, // read |
input wr, // write |
124,7 → 128,12
else begin |
if( rd ) |
data_out=regarray[ adr ]; |
else if( wr ) regarray[adr]=data_in; |
else if( wr ) begin |
regarray[adr]=data_in; |
if( dump_writes ) begin |
$display("#%d, %t, %d, %d", id, $realtime, adr, data_in ); |
end |
end |
end |
end |
|
/sqm/sqm_pwm_1_tb.v
0,0 → 1,44
/* |
SQmusic |
logarithmic PWM controller to use with SQMUSIC |
Version 0.1, tested on simulation only with Capcom's 1942 |
|
(c) Jose Tejada Gomez, 11th May 2013 |
You can use this file following the GNU GENERAL PUBLIC LICENSE version 3 |
Read the details of the license in: |
http://www.gnu.org/licenses/gpl.txt |
|
Send comments to: jose.tejada@ieee.org |
|
*/ |
|
// Compile with: |
// iverilog sqm_pwm_1_tb.v sqm_pwm.v -s sqm_pwm_1_tb -o sqm_pwm_1_tb |
|
`timescale 1ns/1ps |
module sqm_pwm_1_tb; |
|
reg clk; |
always begin |
clk=0; |
#10 clk <= ~clk; |
end |
|
reg [3:0]A; |
always begin |
A=0; |
#5000 A <= A+1; |
end |
|
reg reset_n; |
initial begin |
$dumpvars(); |
$dumpon; |
reset_n=0; |
#15 reset_n=1; |
#80000 $finish; |
end |
|
SQM_PWM_1 apwm( .clk(clk), .reset_n(reset_n), .din(A), .pwm(y_a) ); |
|
endmodule |