Update YM2149 to latest version.

This commit is contained in:
sorgelig
2018-08-22 03:41:30 +08:00
parent dfa92d61b0
commit 7ee1d8a53f
2 changed files with 104 additions and 127 deletions

View File

@ -38,14 +38,6 @@
// 1 0 write value // 1 0 write value
// 1 1 set address // 1 1 set address
// //
// Registers description
// R0, R1, R2, R4, R4, R5 - Tone Generator Control
// R6 - Noise Generator Control
// R7 - Mixer Control-I/O Enable
// R10, R11, R12 - Amplitude Control
// R13, R14, R15 - Envelope Generator Control
// R13, R14 - Envelope Period Control
// R15 - Envelope Shape/Cycle Control
module ym2149 module ym2149
( (
@ -72,42 +64,39 @@ module ym2149
output [7:0] IOB_out output [7:0] IOB_out
); );
assign ACTIVE = ~ymreg[7][5:0]; assign ACTIVE = ~ymreg[7][5:0];
assign IOA_out = ymreg[14];
assign IOB_out = ymreg[15];
assign IOA_out = ymreg[14]; reg [7:0] addr;
assign IOB_out = ymreg[15]; reg [7:0] ymreg[16];
reg ena_div; // Write to PSG
reg ena_div_noise; reg env_reset;
reg [7:0] addr; always @(posedge CLK) begin
reg [7:0] ymreg[16]; if(RESET) begin
reg env_ena; ymreg <= '{default:0};
reg [4:0] env_vol; ymreg[7] <= '1;
addr <= '0;
env_reset <= 0;
end else begin
env_reset <= 0;
if(BDIR) begin
if(BC) addr <= DI;
else if(!addr[7:4]) begin
ymreg[addr[3:0]] <= DI;
env_reset <= (addr == 13);
end
end
end
end
wire [7:0] volTableAy[16] = // Read from PSG
'{8'h00, 8'h03, 8'h04, 8'h06,
8'h0a, 8'h0f, 8'h15, 8'h22,
8'h28, 8'h41, 8'h5b, 8'h72,
8'h90, 8'hb5, 8'hd7, 8'hff
};
wire [7:0] volTableYm[32] =
'{8'h00, 8'h01, 8'h01, 8'h02,
8'h02, 8'h03, 8'h03, 8'h04,
8'h06, 8'h07, 8'h09, 8'h0a,
8'h0c, 8'h0e, 8'h11, 8'h13,
8'h17, 8'h1b, 8'h20, 8'h25,
8'h2c, 8'h35, 8'h3e, 8'h47,
8'h54, 8'h66, 8'h77, 8'h88,
8'ha1, 8'hc0, 8'he0, 8'hff
};
// Read from AY
assign DO = dout; assign DO = dout;
reg [7:0] dout; reg [7:0] dout;
always_comb begin always_comb begin
if(addr[7:4]) dout <= 8'hFF; dout = 8'hFF;
else begin if(~BDIR & BC & !addr[7:4]) begin
case(addr[3:0]) case(addr[3:0])
0: dout = ymreg[0]; 0: dout = ymreg[0];
1: dout = ymreg[1][3:0]; 1: dout = ymreg[1][3:0];
@ -123,12 +112,15 @@ always_comb begin
11: dout = ymreg[11]; 11: dout = ymreg[11];
12: dout = ymreg[12]; 12: dout = ymreg[12];
13: dout = ymreg[13][3:0]; 13: dout = ymreg[13][3:0];
14: dout = (ymreg[7][6] ? ymreg[14] : IOA_in); 14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
15: dout = (ymreg[7][7] ? ymreg[15] : IOB_in); 15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
endcase endcase
end end
end end
reg ena_div;
reg ena_div_noise;
// p_divider // p_divider
always @(posedge CLK) begin always @(posedge CLK) begin
reg [3:0] cnt_div; reg [3:0] cnt_div;
@ -150,7 +142,7 @@ always @(posedge CLK) begin
end end
reg noise_gen_op; reg [2:0] noise_gen_op;
// p_noise_gen // p_noise_gen
always @(posedge CLK) begin always @(posedge CLK) begin
@ -166,9 +158,9 @@ always @(posedge CLK) begin
end else begin end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1; noise_gen_cnt <= noise_gen_cnt + 1'd1;
end end
noise_gen_op <= poly17[0]; noise_gen_op <= {3{poly17[0]}};
end else begin end else begin
noise_gen_op <= 0; noise_gen_op <= ymreg[7][5:3];
noise_gen_cnt <= 0; noise_gen_cnt <= 0;
end end
end end
@ -200,7 +192,7 @@ always @(posedge CLK) begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1; tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end end
end else begin end else begin
tone_gen_op[i] <= 0; tone_gen_op[i] <= ymreg[7][i];
tone_gen_cnt[i] <= 0; tone_gen_cnt[i] <= 0;
end end
end end
@ -208,6 +200,7 @@ always @(posedge CLK) begin
end end
end end
reg env_ena;
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0; wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq //p_envelope_freq
@ -227,14 +220,14 @@ always @(posedge CLK) begin
end end
end end
reg [4:0] env_vol;
wire is_bot = (env_vol == 5'b00000); wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001); wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110); wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111); wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin always @(posedge CLK) begin
reg old_BDIR;
reg env_reset;
reg env_hold; reg env_hold;
reg env_inc; reg env_inc;
@ -260,82 +253,49 @@ always @(posedge CLK) begin
// //
// 1 1 1 1 /___ // 1 1 1 1 /___
if(RESET) begin if(env_reset | RESET) begin
ymreg[0] <= '0; // load initial state
ymreg[1] <= '0; if(!ymreg[13][2]) begin // attack
ymreg[2] <= '0; env_vol <= 5'b11111;
ymreg[3] <= '0; env_inc <= 0; // -1
ymreg[4] <= '0;
ymreg[5] <= '0;
ymreg[6] <= '0;
ymreg[7] <= '1;
ymreg[8] <= '0;
ymreg[9] <= '0;
ymreg[10] <= '0;
ymreg[11] <= '0;
ymreg[12] <= '0;
ymreg[13] <= '0;
ymreg[14] <= '0;
ymreg[15] <= '0;
addr <= '0;
env_vol <= '0;
end else begin
old_BDIR <= BDIR;
if(~old_BDIR & BDIR) begin
if(BC) addr <= DI;
else if(!addr[7:4])begin
ymreg[addr[3:0]] <= DI;
env_reset <= (addr == 13);
end
end
end
if(CE) begin
if(env_reset) begin
env_reset <= 0;
// load initial state
if(!ymreg[13][2]) begin // attack
env_vol <= 5'b11111;
env_inc <= 0; // -1
end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end else begin end else begin
env_vol <= 5'b00000;
env_inc <= 1; // +1
end
env_hold <= 0;
end
else if(CE) begin
if (env_ena) begin
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
if (env_ena) begin // envelope shape control.
if (!env_hold) begin if(!ymreg[13][3]) begin
if (env_inc) env_vol <= (env_vol + 5'b00001); if(!env_inc) begin // down
else env_vol <= (env_vol + 5'b11111); if(is_bot_p1) env_hold <= 1;
end end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
// envelope shape control. if(!env_inc) begin // down
if(!ymreg[13][3]) begin if(ymreg[13][1]) begin // alt
if(!env_inc) begin // down if(is_bot) env_hold <= 1;
if(is_bot_p1) env_hold <= 1; end else if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1; end else if(ymreg[13][1]) begin // alt
end else if(ymreg[13][0]) begin // hold = 1 if(is_top) env_hold <= 1;
if(!env_inc) begin // down end else if(is_top_m1) env_hold <= 1;
if(ymreg[13][1]) begin // alt end else if(ymreg[13][1]) begin // alternate
if(is_bot) env_hold <= 1; if(env_inc == 1'b0) begin // down
end else if(is_bot_p1) env_hold <= 1; if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt if(is_bot) begin
if(is_top) env_hold <= 1; env_hold <= 0;
end else if(is_top_m1) env_hold <= 1; env_inc <= 1;
end else if(ymreg[13][1]) begin // alternate end
if(env_inc == 1'b0) begin // down end else begin
if(is_bot_p1) env_hold <= 1; if(is_top_m1) env_hold <= 1;
if(is_bot) begin if(is_top) begin
env_hold <= 0; env_hold <= 0;
env_inc <= 1; env_inc <= 0;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end end
end end
end end
@ -343,12 +303,29 @@ always @(posedge CLK) begin
end end
end end
wire [4:0] A = ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op)) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}; reg [5:0] A,B,C;
wire [4:0] B = ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op)) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}; always @(posedge CLK) begin
wire [4:0] C = ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op)) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}; A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
end
assign CHANNEL_A = MODE ? volTableAy[A[4:1]] : volTableYm[A]; wire [7:0] volTable[64] = '{
assign CHANNEL_B = MODE ? volTableAy[B[4:1]] : volTableYm[B]; //YM2149
assign CHANNEL_C = MODE ? volTableAy[C[4:1]] : volTableYm[C]; 8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
//AY8910
8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
};
assign CHANNEL_A = volTable[A];
assign CHANNEL_B = volTable[B];
assign CHANNEL_C = volTable[C];
endmodule endmodule

View File

@ -94,7 +94,7 @@ ym2149 ym2149
.CE(ce_psg), .CE(ce_psg),
.RESET(RESET), .RESET(RESET),
.BDIR(WE), .BDIR(WE),
.BC(~A0), .BC(~A0 | ~WE),
.DI(DI), .DI(DI),
.DO(psg_dout), .DO(psg_dout),
.CHANNEL_A(CHANNEL_A), .CHANNEL_A(CHANNEL_A),