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 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
(
@ -72,42 +64,39 @@ module ym2149
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];
assign IOB_out = ymreg[15];
reg [7:0] addr;
reg [7:0] ymreg[16];
reg ena_div;
reg ena_div_noise;
reg [7:0] addr;
reg [7:0] ymreg[16];
reg env_ena;
reg [4:0] env_vol;
// Write to PSG
reg env_reset;
always @(posedge CLK) begin
if(RESET) begin
ymreg <= '{default:0};
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] =
'{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
// Read from PSG
assign DO = dout;
reg [7:0] dout;
always_comb begin
if(addr[7:4]) dout <= 8'hFF;
else begin
dout = 8'hFF;
if(~BDIR & BC & !addr[7:4]) begin
case(addr[3:0])
0: dout = ymreg[0];
1: dout = ymreg[1][3:0];
@ -123,12 +112,15 @@ always_comb begin
11: dout = ymreg[11];
12: dout = ymreg[12];
13: dout = ymreg[13][3:0];
14: dout = (ymreg[7][6] ? ymreg[14] : IOA_in);
15: dout = (ymreg[7][7] ? ymreg[15] : IOB_in);
14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
endcase
end
end
reg ena_div;
reg ena_div_noise;
// p_divider
always @(posedge CLK) begin
reg [3:0] cnt_div;
@ -150,7 +142,7 @@ always @(posedge CLK) begin
end
reg noise_gen_op;
reg [2:0] noise_gen_op;
// p_noise_gen
always @(posedge CLK) begin
@ -166,9 +158,9 @@ always @(posedge CLK) begin
end else begin
noise_gen_cnt <= noise_gen_cnt + 1'd1;
end
noise_gen_op <= poly17[0];
noise_gen_op <= {3{poly17[0]}};
end else begin
noise_gen_op <= 0;
noise_gen_op <= ymreg[7][5:3];
noise_gen_cnt <= 0;
end
end
@ -200,7 +192,7 @@ always @(posedge CLK) begin
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
end
end else begin
tone_gen_op[i] <= 0;
tone_gen_op[i] <= ymreg[7][i];
tone_gen_cnt[i] <= 0;
end
end
@ -208,6 +200,7 @@ always @(posedge CLK) begin
end
end
reg env_ena;
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
//p_envelope_freq
@ -227,14 +220,14 @@ always @(posedge CLK) begin
end
end
reg [4:0] env_vol;
wire is_bot = (env_vol == 5'b00000);
wire is_bot_p1 = (env_vol == 5'b00001);
wire is_top_m1 = (env_vol == 5'b11110);
wire is_top = (env_vol == 5'b11111);
always @(posedge CLK) begin
reg old_BDIR;
reg env_reset;
reg env_hold;
reg env_inc;
@ -260,82 +253,49 @@ always @(posedge CLK) begin
//
// 1 1 1 1 /___
if(RESET) begin
ymreg[0] <= '0;
ymreg[1] <= '0;
ymreg[2] <= '0;
ymreg[3] <= '0;
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;
if(env_reset | RESET) begin
// 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 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
if (!env_hold) begin
if (env_inc) env_vol <= (env_vol + 5'b00001);
else env_vol <= (env_vol + 5'b11111);
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
// envelope shape control.
if(!ymreg[13][3]) begin
if(!env_inc) begin // down
if(is_bot_p1) env_hold <= 1;
end else if (is_top) env_hold <= 1;
end else if(ymreg[13][0]) begin // hold = 1
if(!env_inc) begin // down
if(ymreg[13][1]) begin // alt
if(is_bot) env_hold <= 1;
end else if(is_bot_p1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alt
if(is_top) env_hold <= 1;
end else if(is_top_m1) env_hold <= 1;
end else if(ymreg[13][1]) begin // alternate
if(env_inc == 1'b0) begin // down
if(is_bot_p1) env_hold <= 1;
if(is_bot) begin
env_hold <= 0;
env_inc <= 1;
end
end else begin
if(is_top_m1) env_hold <= 1;
if(is_top) begin
env_hold <= 0;
env_inc <= 0;
end
end
end
@ -343,12 +303,29 @@ always @(posedge CLK) begin
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]};
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]};
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]};
reg [5:0] A,B,C;
always @(posedge CLK) begin
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];
assign CHANNEL_B = MODE ? volTableAy[B[4:1]] : volTableYm[B];
assign CHANNEL_C = MODE ? volTableAy[C[4:1]] : volTableYm[C];
wire [7:0] volTable[64] = '{
//YM2149
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

View File

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