URL
https://opencores.org/ocsvn/sqmusic/sqmusic/trunk
Subversion Repositories sqmusic
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/sqmusic/trunk/1942/computer_1942.v
0,0 → 1,183
/* |
1942 simple board setup in order to test SQMUSIC. |
|
Requirements: |
TV80, Z80 Verilog module |
Dump of Z80 ROM from 1942 board |
|
(c) Jose Tejada Gomez, 9th 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 |
|
*/ |
|
module computer_1942 |
#(parameter dump_regs=0) // set to 1 to dump sqmusic registers |
( |
input clk, |
input sound_clk, |
input reset_n, |
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 [15:0] amp0_y, amp1_y; |
|
wire [7:0]ram_out, rom_out, latch_out; |
wire rom_enable = adr<16'h4000 ? 1:0; |
wire ram_enable = adr>=16'h4000 && adr<16'h4800 ? 1:0; |
wire latch_enable = adr==16'h6000 ? 1 : 0; |
wire ay_0_enable = adr==16'h8000 || adr==16'h8001 ? 1:0; |
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 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); |
*/ |
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)); |
SOUND_LATCH sound_latch( .dout(latch_out), .enable(latch_enable), |
.clk(clk), .rd_n(rd_n) ); |
|
// fake_ay ay_0( .adr(adr[0]), .din(din), .clk(clk), .wr_n(~ay_0_enable|wr_n) ); |
|
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 #(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) ); |
endmodule |
|
////////////////////////////////////////////////////////// |
// this module is used to check the communication of the |
// Z80 with the AY-3-8910 |
// only used for debugging |
module fake_ay( |
input adr, |
input [7:0] din, |
input clk, |
input wr_n ); |
|
reg [7:0] contents[1:0]; |
wire sample = clk & ~wr_n; |
|
always @(posedge sample) begin |
// if( contents[adr] != din ) begin |
$display("%t -> %d = %d", $realtime/1e6, adr, din ); |
if( !adr && din>15 ) $display("AY WARNING"); |
contents[adr] = din; |
end |
|
endmodule |
|
////////////////////////////////////////////////////////// |
module RAM( |
input [10:0] adr, |
input [7:0] din, |
output reg [7:0] dout, |
input enable, |
input clk, |
input rd_n, |
input wr_n ); |
|
reg [7:0] contents[2047:0]; |
wire sample = clk & (~rd_n | ~wr_n ); |
|
initial dout=0; |
|
always @(posedge sample) begin |
if( !enable ) |
dout=0; |
else begin |
if( !wr_n ) contents[adr]=din; |
if( !rd_n ) dout=contents[adr]; |
end |
end |
endmodule |
|
////////////////////////////////////////////////////////// |
module ROM( |
input [13:0] adr, |
output reg [7:0] data, |
input enable, |
input rd_n, |
input clk ); |
|
reg [7:0] contents[16383:0]; |
|
wire sample = clk & ~rd_n; |
|
initial begin |
$readmemh("../rom/sr-01.c11.hex", contents ); // this is the hex dump of the ROM |
data=0; |
end |
|
always @( posedge sample ) begin |
if ( !enable ) |
data=0; |
else |
data=contents[ adr ]; |
end |
endmodule |
|
////////////////////////////////////////////////////////// |
module SOUND_LATCH( |
output reg [7:0] dout, |
input enable, |
input clk, |
input rd_n ); |
|
wire sample = clk & ~rd_n; |
reg [7:0]data; |
|
initial begin |
dout=0; |
data=0; |
#100e6 data=8'h12; // enter the song/sound code here |
end |
|
always @(posedge sample) begin |
if( !enable ) |
dout=0; |
else begin |
if( !rd_n ) begin |
// $display("Audio latch read @ %t us", $realtime/1e6 ); |
// if( data != 0 ) |
// $display("Audio latch read (%X) @ %t us", data, $realtime/1e6 ); |
dout=data; |
end |
end |
end |
endmodule |
/sqmusic/trunk/1942/1942.v
19,6 → 19,7
module sound1942; |
// inputs to Z80 |
reg reset_n, clk, int_n, sound_clk; |
parameter dump_text = 1; // set to 1 to dump data to use log2wav later |
|
initial begin |
/* $dumpfile("dump.lxt"); |
27,12 → 28,13
// $dumpvars(); |
// $dumpon; |
// $shm_open("1942.shm"); |
// $shm_probe( sound1942, "ACTFS" ); |
// $shm_probe( sound1942, "ACTFS" ); |
reset_n=0; |
#1500 reset_n=1; |
$display("1942 START"); |
// change finish time depending on song |
//#4e6 $finish; |
#6e9 $finish; |
//#0.1e9 $finish; |
#7e9 $finish; |
end |
|
always begin // main clock |
73,7 → 75,7
always begin |
vhf_clk=0; |
forever begin |
if( vhf_clk ) begin |
if( vhf_clk && dump_text ) begin |
$display("%d, %d, %d, %d, %d, %d", |
pwm0_a, pwm0_b, pwm0_c, pwm1_a, pwm1_b, pwm1_c ); |
end |
88,176 → 90,6
SQM_PWM_1 a1pwm( .clk(vhf_clk), .reset_n(reset_n), .din(ay1_a), .pwm(pwm1_a) ); |
SQM_PWM_1 b1pwm( .clk(vhf_clk), .reset_n(reset_n), .din(ay1_b), .pwm(pwm1_b) ); |
SQM_PWM_1 c1pwm( .clk(vhf_clk), .reset_n(reset_n), .din(ay1_c), .pwm(pwm1_c) ); |
endmodule |
|
///////////////////////////////////////////////////// |
module computer_1942 |
#(parameter dump_regs=0) // set to 1 to dump sqmusic registers |
( |
input clk, |
input sound_clk, |
input reset_n, |
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; |
|
wire [7:0]ram_out, rom_out, latch_out; |
wire rom_enable = adr<16'h4000 ? 1:0; |
wire ram_enable = adr>=16'h4000 && adr<16'h4800 ? 1:0; |
wire latch_enable = adr==16'h6000 ? 1 : 0; |
wire ay_0_enable = adr==16'h8000 || adr==16'h8001 ? 1:0; |
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 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); |
*/ |
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)); |
SOUND_LATCH sound_latch( .dout(latch_out), .enable(latch_enable), |
.clk(clk), .rd_n(rd_n) ); |
|
// fake_ay ay_0( .adr(adr[0]), .din(din), .clk(clk), .wr_n(~ay_0_enable|wr_n) ); |
|
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 #(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) ); |
endmodule |
|
////////////////////////////////////////////////////////// |
// this module is used to check the communication of the |
// Z80 with the AY-3-8910 |
// only used for debugging |
module fake_ay( |
input adr, |
input [7:0] din, |
input clk, |
input wr_n ); |
|
reg [7:0] contents[1:0]; |
wire sample = clk & ~wr_n; |
|
always @(posedge sample) begin |
// if( contents[adr] != din ) begin |
$display("%t -> %d = %d", $realtime/1e6, adr, din ); |
if( !adr && din>15 ) $display("AY WARNING"); |
contents[adr] = din; |
end |
|
endmodule |
|
////////////////////////////////////////////////////////// |
module RAM( |
input [10:0] adr, |
input [7:0] din, |
output reg [7:0] dout, |
input enable, |
input clk, |
input rd_n, |
input wr_n ); |
|
reg [7:0] contents[2047:0]; |
wire sample = clk & (~rd_n | ~wr_n ); |
|
initial dout=0; |
|
always @(posedge sample) begin |
if( !enable ) |
dout=0; |
else begin |
if( !wr_n ) contents[adr]=din; |
if( !rd_n ) dout=contents[adr]; |
end |
end |
endmodule |
|
////////////////////////////////////////////////////////// |
module ROM( |
input [13:0] adr, |
output reg [7:0] data, |
input enable, |
input rd_n, |
input clk ); |
|
reg [7:0] contents[16383:0]; |
|
wire sample = clk & ~rd_n; |
|
initial begin |
$readmemh("../rom/sr-01.c11.hex", contents ); // this is the hex dump of the ROM |
data=0; |
end |
|
always @( posedge sample ) begin |
if ( !enable ) |
data=0; |
else |
data=contents[ adr ]; |
end |
endmodule |
|
////////////////////////////////////////////////////////// |
module SOUND_LATCH( |
output reg [7:0] dout, |
input enable, |
input clk, |
input rd_n ); |
|
wire sample = clk & ~rd_n; |
reg [7:0]data; |
|
initial begin |
dout=0; |
data=0; |
#100e6 data=8'h12; // enter the song/sound code here |
end |
|
always @(posedge sample) begin |
if( !enable ) |
dout=0; |
else begin |
if( !rd_n ) begin |
// $display("Audio latch read @ %t us", $realtime/1e6 ); |
// if( data != 0 ) |
// $display("Audio latch read (%X) @ %t us", data, $realtime/1e6 ); |
dout=data; |
end |
end |
end |
endmodule |
|
/sqmusic/trunk/1942/log2wav.cc
20,6 → 20,7
#include <assert.h> |
#include <string.h> |
#include <string> |
#include <signal.h> |
|
using namespace std; |
|
65,6 → 66,12
} |
}; |
|
bool sigint_abort=false; |
|
void sigint_handle(int x ) { |
sigint_abort = true; |
} |
|
int main(int argc, char *argv[]) { |
try { |
ifstream fin; |
81,7 → 88,7
// 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 |
// 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; |
88,7 → 95,9
} |
if( fin.eof() ) throw "Data not found"; |
fout.seekp(44); |
while( !fin.eof() && !fin.bad() && !fin.fail() ) { |
signal( 2, sigint_handle ); // capture CTRL+C in order to save the |
// WAV header before quiting |
while( !fin.eof() && !fin.bad() && !fin.fail() && !sigint_abort ) { |
short int value; |
fin.getline( buffer, sizeof(buffer) ); |
|
/sqmusic/trunk/1942/gather
1,4 → 1,5
1942.v |
computer_1942.v |
../tv80/rtl/core/tv80n.v |
../tv80/rtl/core/tv80_core.v |
../tv80/rtl/core/tv80_alu.v |
/sqmusic/trunk/1942/pwm2log.cc
54,7 → 54,9
try { |
long int sample=0; |
// skip first line |
cin.getline( buf, sizeof(buf) ); |
buf[0]=0; |
while( strncmp("1942 START",buf, 11 ) && !cin.eof() && !cin.fail() ) |
cin.getline( buf, sizeof(buf) ); |
|
cin.getline( buf, sizeof(buf) ); |
while( buf[0] && !cin.eof() ) { |
/sqmusic/trunk/sqm/sqm_pwm.v
43,37 → 43,37
|
always @(posedge clk or negedge reset_n) begin |
if( !reset_n ) begin |
count=0; |
last0=0; |
last1=1; |
count<=0; |
last0<=0; |
last1<=1; |
end |
else |
if( zero ) begin |
pwm=0; |
count=0; |
pwm <=0; |
count<=0; |
end |
else if( last0!=rep0 || last1!=rep1 ) begin |
last0 <= rep0; |
last1 <= rep1; |
count = 0; |
pwm=0; |
count <= 0; |
pwm <=0; |
end |
else if( last0==1 && last1==1 ) begin |
pwm=clk; |
count=0; |
pwm <=clk; |
count<=0; |
end |
else begin |
if( pwm && count==last1-1 ) begin |
count=0; |
pwm=0; |
count<=0; |
pwm <=0; |
end |
else if( !pwm && count==last0-1 ) begin |
count=0; |
pwm=1; |
count<=0; |
pwm <=1; |
end |
else begin |
count<=count+1; |
pwm<=pwm; |
pwm <=pwm; |
end |
end |
end |
/sqmusic/trunk/sqm/ay_3_8910_capcom_tb.v
0,0 → 1,75
`timescale 1ns / 1ps |
module ay_3_8910_capcom_tb; |
|
reg reset_n, clk, int_n, sound_clk; |
reg [7:0] data; |
reg wr_n, cs_n, adr; |
parameter dump_text = 1; // set to 1 to dump data to use log2wav later |
|
initial begin |
/* $dumpfile("dump.lxt"); |
$dumpvars(1,pwm0); |
$dumpvars(1,pwm1);*/ |
// $dumpvars(); |
// $dumpon; |
$shm_open( "ay_3_8910_capcom_tb.shm"); |
$shm_probe( ay_3_8910_capcom_tb, "ACTFS" ); |
reset_n=0; |
data=0; |
wr_n=1; |
cs_n=1; |
adr=0; |
#1500 reset_n=1; |
// write 201 to register 15 |
adr=0; |
data=8'h3F; |
wr_n=0; |
cs_n=0; |
#668 |
data=201; |
adr=1; |
#668 |
// write 134 to register 4 |
#668 |
adr=0; |
data=8'h04; |
wr_n=0; |
cs_n=0; |
#668 |
data=134; |
adr=1; |
#668 |
// write 63 to register 12 |
#668 |
adr=0; |
data=12; |
wr_n=0; |
cs_n=0; |
#668 |
data= 63; |
adr=1; |
#668 |
wr_n=1; |
data=0; |
#700 |
$finish; |
end |
|
always begin // main clock |
clk=0; |
forever clk = #167 ~clk; |
end |
|
always begin // sound clock |
sound_clk=0; |
forever sound_clk = #334 ~sound_clk; |
end |
|
|
AY_3_8910_capcom #(1,0) ay( .reset_n(reset_n), .clk(clk), // CPU clock |
.sound_clk(sound_clk), // normally slower than the CPU clock |
.din(data), .adr(adr), .wr_n(wr_n), .cs_n(cs_n), // chip select |
.A(A),.B(B),.C(C) // channel outputs |
); |
|
endmodule |
/sqmusic/trunk/sqm/sqmusic.v
30,39 → 30,24
output [3:0]A,B,C // channel outputs |
); |
|
reg [7:0] latches[1:0]; |
reg core_wr; |
wire sample = clk & ~cs_n & ~wr_n; |
reg [3:0] adr_latch; |
wire sample = ~cs_n & ~wr_n; |
wire core_wr = adr & sample; |
reg count; |
|
always @(posedge sound_clk or negedge reset_n) begin |
if(!reset_n) begin |
count=0; |
end |
else begin |
if( !count && core_wr) count=1; |
else if( core_wr ) begin |
count=0; |
core_wr=0; |
end |
end |
always @(posedge clk or negedge reset_n) begin |
if(!reset_n) |
adr_latch <= 0; |
else |
if( sample && adr==0 ) |
adr_latch <= din[3:0]; |
end |
|
always @(posedge sample or negedge reset_n) begin |
if(!reset_n) begin |
latches[0]=0; |
latches[1]=0; |
end |
else begin |
latches[adr] = din; |
if(adr) core_wr=1; |
end |
end |
|
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) ); |
SQMUSIC #(dump_writes, id) core( .reset_n(reset_n), .clk(sound_clk), .data_in(din), |
.adr( adr_latch ), .rd(1'b0), .wr(core_wr), .A(A), .B(B), .C(C) ); |
endmodule |
|
////////////////////////////////////////////////////////////////////////////// |
/* The AY core does |
*/ |
module SQMUSIC |
110,17 → 95,16
assign B=regarray[11][4]? envelope&{4{Bmix}} : regarray[10][3:0]&{4{Bmix}}; |
assign C=regarray[12][4]? envelope&{4{Cmix}} : regarray[10][3:0]&{4{Cmix}}; |
|
integer aux; |
|
// 16-count divider |
always @(posedge clk or reset_n) begin |
always @(posedge clk or negedge reset_n) begin |
if( !reset_n) |
clkdiv16=0; |
clkdiv16<=0; |
else |
clkdiv16<=clkdiv16+1; |
end |
|
always @(posedge clk or reset_n) begin |
integer aux; |
always @(posedge clk or negedge reset_n) begin |
if( !reset_n ) begin |
data_out=0; |
for(aux=0;aux<=15;aux=aux+1) regarray[aux]=0; |
159,10 → 143,10
|
assign div = period==1 ? clk : clkdiv; |
|
always @(posedge clk or reset_n) begin |
always @(posedge clk or negedge reset_n) begin |
if( !reset_n) begin |
count=0; |
clkdiv=0; |
count<=0; |
clkdiv<=0; |
end |
else begin |
if( period==0 ) begin |
171,7 → 155,7
end |
else if( count >= period ) begin |
count <= 0; |
clkdiv = ~clkdiv; |
clkdiv <= ~clkdiv; |
end |
else count <= count+1; |
end |
192,12 → 176,12
assign noise=poly17[16]; |
wire noise_clk; |
|
always @(posedge noise_clk or reset_n) begin |
always @(posedge noise_clk or negedge reset_n) begin |
if( !reset_n) begin |
poly17=0; |
poly17<=0; |
end |
else begin |
poly17={ poly17[0] ^ poly17[2] ^ poly17_zero, poly17[16:1] }; |
poly17<={ poly17[0] ^ poly17[2] ^ poly17_zero, poly17[16:1] }; |
end |
end |
|
217,12 → 201,12
reg stop; |
reg [3:0]prev_ctrl; // last control orders |
|
always @(posedge clk or reset_n) begin |
always @(posedge clk or negedge reset_n) begin |
if( !reset_n) begin |
gain=4'hF; |
dir=0; |
prev_ctrl=0; |
stop=1; |
gain<=4'hF; |
dir<=0; |
prev_ctrl<=0; |
stop<=1; |
end |
else begin |
if (ctrl!=prev_ctrl) begin |