diff --git a/verilog/sd2snes/address.v b/verilog/sd2snes/address.v
index 5defd3f..98ced2a 100644
--- a/verilog/sd2snes/address.v
+++ b/verilog/sd2snes/address.v
@@ -32,7 +32,9 @@ module address(
input ADDR_WRITE,
output ROM_ADDR0,
input [23:0] SAVERAM_MASK,
- input [23:0] ROM_MASK
+ input [23:0] ROM_MASK,
+ input use_msu,
+ output msu_enable
);
wire [1:0] SRAM_BANK;
@@ -102,5 +104,7 @@ assign ROM_ADDR = SRAM_ADDR_FULL[23:1];
assign ROM_SEL = 1'b0; // (MODE) ? CS_ARRAY[SRAM_BANK] : IS_SAVERAM ? 4'b1000 : CS_ARRAY[SRAM_BANK];
assign ROM_ADDR0 = SRAM_ADDR_FULL[0];
+//488888
+assign msu_enable = (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000));
endmodule
diff --git a/verilog/sd2snes/avr_cmd.v b/verilog/sd2snes/avr_cmd.v
index f643d19..5065213 100644
--- a/verilog/sd2snes/avr_cmd.v
+++ b/verilog/sd2snes/avr_cmd.v
@@ -40,12 +40,34 @@ module mcu_cmd(
output [23:0] saveram_mask_out,
output [23:0] rom_mask_out,
- // SPI "DMA" extension
+ // SD "DMA" extension
output SD_DMA_EN,
input SD_DMA_STATUS,
input SD_DMA_NEXTADDR,
input [7:0] SD_DMA_SRAM_DATA,
- input SD_DMA_SRAM_WE
+ input SD_DMA_SRAM_WE,
+ output [1:0] SD_DMA_TGT,
+ output SD_DMA_PARTIAL,
+ output [11:0] SD_DMA_PARTIAL_START,
+ output [11:0] SD_DMA_PARTIAL_END,
+
+ // DAC
+ output [10:0] dac_addr_out,
+// output [7:0] dac_volume_out,
+// output dac_volume_latch_out,
+ input DAC_STATUS,
+ output dac_play_out,
+ output dac_reset_out,
+
+ // MSU data
+ output [13:0] msu_addr_out,
+ input [6:0] MSU_STATUS,
+ output [5:0] msu_status_reset_out,
+ output [5:0] msu_status_set_out,
+ output msu_status_reset_we,
+ input [31:0] msu_addressrq,
+ input [15:0] msu_trackrq,
+ input [7:0] msu_volumerq
);
reg [3:0] MAPPER_BUF;
@@ -53,14 +75,46 @@ reg [3:0] SRAM_SIZE_BUF;
reg MCU_READ_BUF;
reg MCU_WRITE_BUF;
reg [23:0] ADDR_OUT_BUF;
+reg [10:0] DAC_ADDR_OUT_BUF;
+reg [7:0] DAC_VOL_OUT_BUF;
+reg DAC_VOL_LATCH_BUF;
+reg DAC_PLAY_OUT_BUF;
+reg DAC_RESET_OUT_BUF;
+reg [13:0] MSU_ADDR_OUT_BUF;
+reg [5:0] msu_status_set_out_buf;
+reg [5:0] msu_status_reset_out_buf;
+reg msu_status_reset_we_buf;
reg [7:0] MCU_DATA_OUT_BUF;
reg [7:0] MCU_DATA_IN_BUF;
reg [1:0] mcu_nextaddr_buf;
+reg SD_DMA_NEXTADDRr;
+always @(posedge clk) SD_DMA_NEXTADDRr <= SD_DMA_NEXTADDR;
+
wire mcu_nextaddr;
+reg DAC_STATUSr;
+reg SD_DMA_STATUSr;
+reg [6:0] MSU_STATUSr;
+always @(posedge clk) begin
+ DAC_STATUSr <= DAC_STATUS;
+ SD_DMA_STATUSr <= SD_DMA_STATUS;
+ MSU_STATUSr <= MSU_STATUS;
+end
+
+reg SD_DMA_PARTIALr;
+assign SD_DMA_PARTIAL = SD_DMA_PARTIALr;
+
reg SD_DMA_ENr;
assign SD_DMA_EN = SD_DMA_ENr;
+reg [1:0] SD_DMA_TGTr;
+assign SD_DMA_TGT = SD_DMA_TGTr;
+
+reg [11:0] SD_DMA_PARTIAL_STARTr;
+reg [11:0] SD_DMA_PARTIAL_ENDr;
+assign SD_DMA_PARTIAL_START = SD_DMA_PARTIAL_STARTr;
+assign SD_DMA_PARTIAL_END = SD_DMA_PARTIAL_ENDr;
+
reg [2:0] spi_dma_nextaddr_r;
reg [1:0] SRAM_MASK_IDX;
@@ -71,6 +125,10 @@ assign spi_data_out = MCU_DATA_IN_BUF;
initial begin
ADDR_OUT_BUF = 0;
+ DAC_ADDR_OUT_BUF = 0;
+ MSU_ADDR_OUT_BUF = 0;
+ DAC_VOL_OUT_BUF = 0;
+ DAC_VOL_LATCH_BUF = 0;
spi_dma_nextaddr_r = 0;
SD_DMA_ENr = 0;
end
@@ -81,25 +139,51 @@ always @(posedge clk) begin
case (cmd_data[7:4])
4'h3: // select mapper
MAPPER_BUF <= cmd_data[3:0];
- 4'h4: // SD DMA
+ 4'h4: begin// SD DMA
SD_DMA_ENr <= 1;
+ SD_DMA_TGTr <= cmd_data[1:0];
+ SD_DMA_PARTIALr <= cmd_data[2];
+ end
// 4'hE:
// select memory unit
endcase
end else if (param_ready) begin
- case (cmd_data[7:0])
- 8'h00:
- case (spi_byte_cnt)
- 32'h2: begin
- ADDR_OUT_BUF[23:16] <= param_data;
- ADDR_OUT_BUF[15:0] <= 16'b0;
- end
- 32'h3:
- ADDR_OUT_BUF[15:8] <= param_data;
- 32'h4:
- ADDR_OUT_BUF[7:0] <= param_data;
- endcase
- 8'h01:
+ casex (cmd_data[7:0])
+ 8'h0x:
+ case (cmd_data[1:0])
+ 2'b01: begin
+ case (spi_byte_cnt)
+ 32'h2: begin
+ DAC_ADDR_OUT_BUF[10:8] <= param_data[2:0];
+ DAC_ADDR_OUT_BUF[7:0] <= 8'b0;
+ end
+ 32'h3:
+ DAC_ADDR_OUT_BUF[7:0] <= param_data;
+ endcase
+ end
+ 2'b10: begin
+ case (spi_byte_cnt)
+ 32'h2: begin
+ MSU_ADDR_OUT_BUF[13:8] <= param_data[5:0];
+ MSU_ADDR_OUT_BUF[7:0] <= 8'b0;
+ end
+ 32'h3:
+ MSU_ADDR_OUT_BUF[7:0] <= param_data;
+ endcase
+ end
+ default:
+ case (spi_byte_cnt)
+ 32'h2: begin
+ ADDR_OUT_BUF[23:16] <= param_data;
+ ADDR_OUT_BUF[15:0] <= 16'b0;
+ end
+ 32'h3:
+ ADDR_OUT_BUF[15:8] <= param_data;
+ 32'h4:
+ ADDR_OUT_BUF[7:0] <= param_data;
+ endcase
+ endcase
+ 8'h1x:
case (spi_byte_cnt)
32'h2:
ROM_MASK[23:16] <= param_data;
@@ -108,7 +192,7 @@ always @(posedge clk) begin
32'h4:
ROM_MASK[7:0] <= param_data;
endcase
- 8'h02:
+ 8'h2x:
case (spi_byte_cnt)
32'h2:
SAVERAM_MASK[23:16] <= param_data;
@@ -117,16 +201,62 @@ always @(posedge clk) begin
32'h4:
SAVERAM_MASK[7:0] <= param_data;
endcase
- 8'h40:
+ 8'h4x:
SD_DMA_ENr <= 1'b0;
- 8'h90:
- MCU_DATA_OUT_BUF <= param_data;
- 8'h91:
+// 8'h5x:
+// case (spi_byte_cnt)
+// 32'h2:
+// DAC_VOL_OUT_BUF <= param_data;
+// 32'h3:
+// DAC_VOL_LATCH_BUF <= 1'b1;
+// 32'h4:
+// DAC_VOL_LATCH_BUF <= 1'b0;
+// endcase
+ 8'h6x:
+ case (spi_byte_cnt)
+ 32'h2:
+ SD_DMA_PARTIAL_STARTr[10:9] <= param_data[1:0];
+ 32'h3:
+ SD_DMA_PARTIAL_STARTr[8:0] <= {param_data, 1'b0};
+ 32'h4:
+ SD_DMA_PARTIAL_ENDr[10:9] <= param_data[1:0];
+ 32'h5:
+ SD_DMA_PARTIAL_ENDr[8:0] <= {param_data, 1'b0};
+ endcase
+ 8'h9x:
MCU_DATA_OUT_BUF <= param_data;
+ 8'he0:
+ case (spi_byte_cnt)
+ 32'h2: begin
+ msu_status_set_out_buf <= param_data[5:0];
+ end
+ 32'h3: begin
+ msu_status_reset_out_buf <= param_data[5:0];
+ msu_status_reset_we_buf <= 1'b1;
+ end
+ 32'h4:
+ msu_status_reset_we_buf <= 1'b0;
+ endcase
+ 8'he1: // pause DAC
+ DAC_PLAY_OUT_BUF <= 1'b0;
+ 8'he2: // resume DAC
+ DAC_PLAY_OUT_BUF <= 1'b1;
+ 8'he3: // reset DAC (set DAC playback address = 0)
+ case (spi_byte_cnt)
+ 32'h2:
+ DAC_RESET_OUT_BUF <= 1'b1;
+ 32'h3:
+ DAC_RESET_OUT_BUF <= 1'b0;
+ endcase
endcase
end
- if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4) && (cmd_data[0]) && (spi_byte_cnt > (32'h1+cmd_data[4]))))
- ADDR_OUT_BUF <= ADDR_OUT_BUF + 1;
+ if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4) && (cmd_data[0]) && (spi_byte_cnt > (32'h1+cmd_data[4])))) begin
+ case (SD_DMA_TGTr)
+ 2'b00: ADDR_OUT_BUF <= ADDR_OUT_BUF + 1;
+ 2'b01: DAC_ADDR_OUT_BUF <= DAC_ADDR_OUT_BUF + 1;
+ 2'b10: MSU_ADDR_OUT_BUF <= MSU_ADDR_OUT_BUF + 1;
+ endcase
+ end
end
// value fetch during last SPI bit
@@ -135,11 +265,39 @@ always @(posedge clk) begin
if (cmd_data[7:0] == 8'hF0)
MCU_DATA_IN_BUF <= 8'hA5;
else if (cmd_data[7:0] == 8'hF1)
- MCU_DATA_IN_BUF <= {SD_DMA_STATUS, 7'b0};
+ case (spi_byte_cnt[0])
+ 1'b1: // buffer status
+ MCU_DATA_IN_BUF <= {SD_DMA_STATUSr, DAC_STATUSr, MSU_STATUSr[6], 5'b0};
+ 1'b0: // control status
+ MCU_DATA_IN_BUF <= {2'b0, MSU_STATUSr[5:0]};
+ endcase
+ else if (cmd_data[7:0] == 8'hF2)
+ case (spi_byte_cnt)
+ 32'h1:
+ MCU_DATA_IN_BUF <= msu_addressrq[31:24];
+ 32'h2:
+ MCU_DATA_IN_BUF <= msu_addressrq[23:16];
+ 32'h3:
+ MCU_DATA_IN_BUF <= msu_addressrq[15:8];
+ 32'h4:
+ MCU_DATA_IN_BUF <= msu_addressrq[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hF3)
+ case (spi_byte_cnt)
+ 23'h1:
+ MCU_DATA_IN_BUF <= msu_trackrq[15:8];
+ 23'h2:
+ MCU_DATA_IN_BUF <= msu_trackrq[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hF4)
+ MCU_DATA_IN_BUF <= msu_volumerq;
else if (cmd_data[7:0] == 8'hFF)
MCU_DATA_IN_BUF <= param_data;
- else
+ else if (cmd_data[7:4] == 4'h8)
MCU_DATA_IN_BUF <= mcu_data_in;
+ else
+ MCU_DATA_IN_BUF <= cmd_data;
+
end
// nextaddr pulse generation
@@ -170,8 +328,17 @@ end
assign mcu_nextaddr = mcu_nextaddr_buf == 2'b01;
assign mcu_read = MCU_READ_BUF;
-assign mcu_write = SD_DMA_STATUS ? SD_DMA_SRAM_WE : MCU_WRITE_BUF;
+assign mcu_write = SD_DMA_STATUS ? (SD_DMA_TGTr == 2'b00 ? SD_DMA_SRAM_WE : 1'b1) : MCU_WRITE_BUF;
assign addr_out = ADDR_OUT_BUF;
+assign dac_addr_out = DAC_ADDR_OUT_BUF;
+assign msu_addr_out = MSU_ADDR_OUT_BUF;
+assign dac_volume_out = DAC_VOL_OUT_BUF;
+assign dac_volume_latch_out = DAC_VOL_LATCH_BUF;
+assign dac_play_out = DAC_PLAY_OUT_BUF;
+assign dac_reset_out = DAC_RESET_OUT_BUF;
+assign msu_status_reset_we = msu_status_reset_we_buf;
+assign msu_status_reset_out = msu_status_reset_out_buf;
+assign msu_status_set_out = msu_status_set_out_buf;
assign mcu_data_out = SD_DMA_STATUS ? SD_DMA_SRAM_DATA : MCU_DATA_OUT_BUF;
assign mcu_mapper = MAPPER_BUF;
assign mcu_sram_size = SRAM_SIZE_BUF;
diff --git a/verilog/sd2snes/dac_test.v b/verilog/sd2snes/dac_test.v
index 1a78ba2..b268eec 100644
--- a/verilog/sd2snes/dac_test.v
+++ b/verilog/sd2snes/dac_test.v
@@ -20,51 +20,116 @@
//////////////////////////////////////////////////////////////////////////////////
module dac_test(
input clkin,
+ input we,
+ input[10:0] pgm_address,
+ input[7:0] pgm_data,
+ input[7:0] volume,
+ input vol_latch,
+ input play,
+ input reset,
output sdout,
output lrck,
- output mclk
+ output mclk,
+ output DAC_STATUS
);
-
+
+reg[8:0] dac_address_r;
+wire[8:0] dac_address = dac_address_r;
+reg dac_nextaddr_r;
+
+wire[31:0] dac_data;
+assign DAC_STATUS = dac_address_r[8];
+reg[7:0] vol_reg;
+reg[7:0] vol_target_reg;
+reg[1:0] vol_latch_reg;
+reg vol_valid;
+
+dac_buf snes_dac_buf (
+ .clka(clkin),
+ .wea(~we), // Bus [0 : 0]
+ .addra(pgm_address), // Bus [10 : 0]
+ .dina(pgm_data), // Bus [7 : 0]
+ .clkb(clkin),
+ .addrb(dac_address), // Bus [9 : 0]
+ .doutb(dac_data)); // Bus [15 : 0]
+
reg [15:0] cnt;
reg [15:0] smpcnt;
+reg [15:0] samples;
wire [15:0] sample = {smpcnt[10] ? ~smpcnt[9:0] : smpcnt[9:0], 6'b0};
wire [15:0] sample2 = {smpcnt[9] ? ~smpcnt[8:0] : smpcnt[8:0], 7'b0};
reg [15:0] smpshift;
+reg [15:0] smpdata;
-assign mclk = cnt[3]; // mclk = clk/8
-assign lrck = cnt[11]; // lrck = mclk/256
-wire sclk = cnt[6]; // sclk = lrck*32
+assign mclk = cnt[2]; // mclk = clk/8
+assign lrck = cnt[10]; // lrck = mclk/256
+wire sclk = cnt[5]; // sclk = lrck*32
-reg [7:0] volume;
-reg [1:0] lrck_sreg;
-reg sclk_sreg;
-wire lrck_rising = ({lrck_sreg[0],lrck} == 2'b01);
-wire lrck_falling = ({lrck_sreg[0],lrck} == 2'b10);
+reg [2:0] lrck_sreg;
+reg [2:0] sclk_sreg;
+wire lrck_rising = ({lrck_sreg[2:1]} == 2'b01);
+wire lrck_falling = ({lrck_sreg[2:1]} == 2'b10);
-wire sclk_rising = ({sclk_sreg, sclk} == 2'b01);
+wire sclk_rising = ({sclk_sreg[2:1]} == 2'b01);
+wire vol_latch_rising = (vol_latch_reg[1:0] == 2'b01);
reg sdout_reg;
assign sdout = sdout_reg;
+reg [1:0] reset_sreg;
+wire reset_rising = (reset_sreg[1:0] == 2'b01);
+
+reg play_r;
+
initial begin
- cnt = 16'b0;
+ cnt = 16'hff00;
smpcnt = 16'b0;
- lrck_sreg = 2'b0;
+ lrck_sreg = 2'b11;
sclk_sreg = 1'b0;
- volume = 8'b0;
+ dac_address_r = 11'b0;
+ vol_valid = 1'b0;
+ vol_latch_reg = 1'b0;
+ vol_reg = 8'h0;
+ vol_target_reg = 8'h0;
+ samples <= 16'h0;
end
always @(posedge clkin) begin
cnt <= cnt + 1;
- lrck_sreg <= {lrck_sreg[0], lrck};
- sclk_sreg <= sclk;
+ lrck_sreg <= {lrck_sreg[1:0], lrck};
+ sclk_sreg <= {sclk_sreg[1:0], sclk};
+ vol_latch_reg <= {vol_latch_reg[0], vol_latch};
+ play_r <= play;
+ reset_sreg <= {reset_sreg[0], reset};
+end
+
+always @(posedge clkin) begin
+ if (vol_latch_rising) begin
+ vol_valid <= 1'b1;
+ end
+ else if(vol_valid) begin
+ vol_target_reg <= volume;
+ vol_valid <= 1'b0;
+ end
+end
+
+// ramp volume only every 4 samples
+always @(posedge clkin) begin
+ if (lrck_rising && &samples[1:0]) begin
+ if(vol_reg > vol_target_reg)
+ vol_reg <= vol_reg - 1;
+ else if(vol_reg < vol_target_reg)
+ vol_reg <= vol_reg + 1;
+ end
end
always @(posedge clkin) begin
if (lrck_rising) begin // right channel
- smpshift <= (({16'h0, sample} * volume) >> 8) ^ 16'h8000; // convert to signed
+ smpshift <= (({16'h0, dac_data[31:16]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
+ dac_address_r <= reset_rising ? 9'h0 : (dac_address_r + play_r);
+ samples <= samples + 1;
end else if (lrck_falling) begin // left channel
- smpshift <= (({16'h0, sample2} * volume) >> 8) ^ 16'h8000;
+ smpshift <= (({16'h0, dac_data[15:0]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
end else begin
if (sclk_rising) begin
smpcnt <= smpcnt + 1;
diff --git a/verilog/sd2snes/data.v b/verilog/sd2snes/data.v
index 16e8545..1a18cb2 100644
--- a/verilog/sd2snes/data.v
+++ b/verilog/sd2snes/data.v
@@ -34,7 +34,10 @@ module data(
input ROM_DATA_TO_SNES_MEM,
input ROM_DATA_TO_MCU_MEM,
input MCU_OVR,
- input ROM_ADDR0
+ input ROM_ADDR0,
+ output [7:0] MSU_DATA_IN,
+ input [7:0] MSU_DATA_OUT,
+ input msu_enable
);
reg [7:0] SNES_IN_MEM;
@@ -44,7 +47,9 @@ reg [7:0] MCU_OUT_MEM;
wire [7:0] FROM_ROM_BYTE;
-assign SNES_DATA = SNES_READ ? 8'bZ : (!MCU_OVR ? 8'h00 : SNES_OUT_MEM);
+assign MSU_DATA_IN = SNES_DATA;
+
+assign SNES_DATA = SNES_READ ? 8'bZ : (!MCU_OVR ? 8'h00 : (msu_enable ? MSU_DATA_OUT : SNES_OUT_MEM));
assign FROM_ROM_BYTE = (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]);
diff --git a/verilog/sd2snes/ipcore_dir/dac_buf.v b/verilog/sd2snes/ipcore_dir/dac_buf.v
new file mode 100644
index 0000000..f84343f
--- /dev/null
+++ b/verilog/sd2snes/ipcore_dir/dac_buf.v
@@ -0,0 +1,145 @@
+/*******************************************************************************
+* This file is owned and controlled by Xilinx and must be used *
+* solely for design, simulation, implementation and creation of *
+* design files limited to Xilinx devices or technologies. Use *
+* with non-Xilinx devices or technologies is expressly prohibited *
+* and immediately terminates your license. *
+* *
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" *
+* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR *
+* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION *
+* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION *
+* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS *
+* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, *
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE *
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY *
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE *
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR *
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF *
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
+* FOR A PARTICULAR PURPOSE. *
+* *
+* Xilinx products are not intended for use in life support *
+* appliances, devices, or systems. Use in such applications are *
+* expressly prohibited. *
+* *
+* (c) Copyright 1995-2009 Xilinx, Inc. *
+* All rights reserved. *
+*******************************************************************************/
+// The synthesis directives "translate_off/translate_on" specified below are
+// supported by Xilinx, Mentor Graphics and Synplicity synthesis
+// tools. Ensure they are correct for your synthesis tool(s).
+
+// You must compile the wrapper file dac_buf.v when simulating
+// the core, dac_buf. When compiling the wrapper file, be sure to
+// reference the XilinxCoreLib Verilog simulation library. For detailed
+// instructions, please refer to the "CORE Generator Help".
+
+`timescale 1ns/1ps
+
+module dac_buf(
+ clka,
+ wea,
+ addra,
+ dina,
+ clkb,
+ addrb,
+ doutb);
+
+
+input clka;
+input [0 : 0] wea;
+input [10 : 0] addra;
+input [7 : 0] dina;
+input clkb;
+input [8 : 0] addrb;
+output [31 : 0] doutb;
+
+// synthesis translate_off
+
+ BLK_MEM_GEN_V4_3 #(
+ .C_ADDRA_WIDTH(11),
+ .C_ADDRB_WIDTH(9),
+ .C_ALGORITHM(1),
+ .C_BYTE_SIZE(9),
+ .C_COMMON_CLK(1),
+ .C_DEFAULT_DATA("0"),
+ .C_DISABLE_WARN_BHV_COLL(0),
+ .C_DISABLE_WARN_BHV_RANGE(0),
+ .C_FAMILY("spartan3"),
+ .C_HAS_ENA(0),
+ .C_HAS_ENB(0),
+ .C_HAS_INJECTERR(0),
+ .C_HAS_MEM_OUTPUT_REGS_A(0),
+ .C_HAS_MEM_OUTPUT_REGS_B(0),
+ .C_HAS_MUX_OUTPUT_REGS_A(0),
+ .C_HAS_MUX_OUTPUT_REGS_B(0),
+ .C_HAS_REGCEA(0),
+ .C_HAS_REGCEB(0),
+ .C_HAS_RSTA(0),
+ .C_HAS_RSTB(0),
+ .C_HAS_SOFTECC_INPUT_REGS_A(0),
+ .C_HAS_SOFTECC_OUTPUT_REGS_B(0),
+ .C_INITA_VAL("0"),
+ .C_INITB_VAL("0"),
+ .C_INIT_FILE_NAME("no_coe_file_loaded"),
+ .C_LOAD_INIT_FILE(0),
+ .C_MEM_TYPE(1),
+ .C_MUX_PIPELINE_STAGES(0),
+ .C_PRIM_TYPE(1),
+ .C_READ_DEPTH_A(2048),
+ .C_READ_DEPTH_B(512),
+ .C_READ_WIDTH_A(8),
+ .C_READ_WIDTH_B(32),
+ .C_RSTRAM_A(0),
+ .C_RSTRAM_B(0),
+ .C_RST_PRIORITY_A("CE"),
+ .C_RST_PRIORITY_B("CE"),
+ .C_RST_TYPE("SYNC"),
+ .C_SIM_COLLISION_CHECK("ALL"),
+ .C_USE_BYTE_WEA(0),
+ .C_USE_BYTE_WEB(0),
+ .C_USE_DEFAULT_DATA(0),
+ .C_USE_ECC(0),
+ .C_USE_SOFTECC(0),
+ .C_WEA_WIDTH(1),
+ .C_WEB_WIDTH(1),
+ .C_WRITE_DEPTH_A(2048),
+ .C_WRITE_DEPTH_B(512),
+ .C_WRITE_MODE_A("WRITE_FIRST"),
+ .C_WRITE_MODE_B("WRITE_FIRST"),
+ .C_WRITE_WIDTH_A(8),
+ .C_WRITE_WIDTH_B(32),
+ .C_XDEVICEFAMILY("spartan3"))
+ inst (
+ .CLKA(clka),
+ .WEA(wea),
+ .ADDRA(addra),
+ .DINA(dina),
+ .CLKB(clkb),
+ .ADDRB(addrb),
+ .DOUTB(doutb),
+ .RSTA(),
+ .ENA(),
+ .REGCEA(),
+ .DOUTA(),
+ .RSTB(),
+ .ENB(),
+ .REGCEB(),
+ .WEB(),
+ .DINB(),
+ .INJECTSBITERR(),
+ .INJECTDBITERR(),
+ .SBITERR(),
+ .DBITERR(),
+ .RDADDRECC());
+
+
+// synthesis translate_on
+
+// XST black box declaration
+// box_type "black_box"
+// synthesis attribute box_type of dac_buf is "black_box"
+
+endmodule
+
diff --git a/verilog/sd2snes/ipcore_dir/dac_buf.xise b/verilog/sd2snes/ipcore_dir/dac_buf.xise
new file mode 100644
index 0000000..7c8d125
--- /dev/null
+++ b/verilog/sd2snes/ipcore_dir/dac_buf.xise
@@ -0,0 +1,382 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes/ipcore_dir/msu_databuf.v b/verilog/sd2snes/ipcore_dir/msu_databuf.v
new file mode 100644
index 0000000..c2a0a23
--- /dev/null
+++ b/verilog/sd2snes/ipcore_dir/msu_databuf.v
@@ -0,0 +1,145 @@
+/*******************************************************************************
+* This file is owned and controlled by Xilinx and must be used *
+* solely for design, simulation, implementation and creation of *
+* design files limited to Xilinx devices or technologies. Use *
+* with non-Xilinx devices or technologies is expressly prohibited *
+* and immediately terminates your license. *
+* *
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" *
+* SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR *
+* XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION *
+* AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION *
+* OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS *
+* IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, *
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE *
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY *
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE *
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR *
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF *
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
+* FOR A PARTICULAR PURPOSE. *
+* *
+* Xilinx products are not intended for use in life support *
+* appliances, devices, or systems. Use in such applications are *
+* expressly prohibited. *
+* *
+* (c) Copyright 1995-2009 Xilinx, Inc. *
+* All rights reserved. *
+*******************************************************************************/
+// The synthesis directives "translate_off/translate_on" specified below are
+// supported by Xilinx, Mentor Graphics and Synplicity synthesis
+// tools. Ensure they are correct for your synthesis tool(s).
+
+// You must compile the wrapper file msu_databuf.v when simulating
+// the core, msu_databuf. When compiling the wrapper file, be sure to
+// reference the XilinxCoreLib Verilog simulation library. For detailed
+// instructions, please refer to the "CORE Generator Help".
+
+`timescale 1ns/1ps
+
+module msu_databuf(
+ clka,
+ wea,
+ addra,
+ dina,
+ clkb,
+ addrb,
+ doutb);
+
+
+input clka;
+input [0 : 0] wea;
+input [13 : 0] addra;
+input [7 : 0] dina;
+input clkb;
+input [13 : 0] addrb;
+output [7 : 0] doutb;
+
+// synthesis translate_off
+
+ BLK_MEM_GEN_V4_3 #(
+ .C_ADDRA_WIDTH(14),
+ .C_ADDRB_WIDTH(14),
+ .C_ALGORITHM(1),
+ .C_BYTE_SIZE(9),
+ .C_COMMON_CLK(1),
+ .C_DEFAULT_DATA("0"),
+ .C_DISABLE_WARN_BHV_COLL(0),
+ .C_DISABLE_WARN_BHV_RANGE(0),
+ .C_FAMILY("spartan3"),
+ .C_HAS_ENA(0),
+ .C_HAS_ENB(0),
+ .C_HAS_INJECTERR(0),
+ .C_HAS_MEM_OUTPUT_REGS_A(0),
+ .C_HAS_MEM_OUTPUT_REGS_B(0),
+ .C_HAS_MUX_OUTPUT_REGS_A(0),
+ .C_HAS_MUX_OUTPUT_REGS_B(0),
+ .C_HAS_REGCEA(0),
+ .C_HAS_REGCEB(0),
+ .C_HAS_RSTA(0),
+ .C_HAS_RSTB(0),
+ .C_HAS_SOFTECC_INPUT_REGS_A(0),
+ .C_HAS_SOFTECC_OUTPUT_REGS_B(0),
+ .C_INITA_VAL("0"),
+ .C_INITB_VAL("0"),
+ .C_INIT_FILE_NAME("no_coe_file_loaded"),
+ .C_LOAD_INIT_FILE(0),
+ .C_MEM_TYPE(1),
+ .C_MUX_PIPELINE_STAGES(0),
+ .C_PRIM_TYPE(1),
+ .C_READ_DEPTH_A(16384),
+ .C_READ_DEPTH_B(16384),
+ .C_READ_WIDTH_A(8),
+ .C_READ_WIDTH_B(8),
+ .C_RSTRAM_A(0),
+ .C_RSTRAM_B(0),
+ .C_RST_PRIORITY_A("CE"),
+ .C_RST_PRIORITY_B("CE"),
+ .C_RST_TYPE("SYNC"),
+ .C_SIM_COLLISION_CHECK("ALL"),
+ .C_USE_BYTE_WEA(0),
+ .C_USE_BYTE_WEB(0),
+ .C_USE_DEFAULT_DATA(0),
+ .C_USE_ECC(0),
+ .C_USE_SOFTECC(0),
+ .C_WEA_WIDTH(1),
+ .C_WEB_WIDTH(1),
+ .C_WRITE_DEPTH_A(16384),
+ .C_WRITE_DEPTH_B(16384),
+ .C_WRITE_MODE_A("WRITE_FIRST"),
+ .C_WRITE_MODE_B("WRITE_FIRST"),
+ .C_WRITE_WIDTH_A(8),
+ .C_WRITE_WIDTH_B(8),
+ .C_XDEVICEFAMILY("spartan3"))
+ inst (
+ .CLKA(clka),
+ .WEA(wea),
+ .ADDRA(addra),
+ .DINA(dina),
+ .CLKB(clkb),
+ .ADDRB(addrb),
+ .DOUTB(doutb),
+ .RSTA(),
+ .ENA(),
+ .REGCEA(),
+ .DOUTA(),
+ .RSTB(),
+ .ENB(),
+ .REGCEB(),
+ .WEB(),
+ .DINB(),
+ .INJECTSBITERR(),
+ .INJECTDBITERR(),
+ .SBITERR(),
+ .DBITERR(),
+ .RDADDRECC());
+
+
+// synthesis translate_on
+
+// XST black box declaration
+// box_type "black_box"
+// synthesis attribute box_type of msu_databuf is "black_box"
+
+endmodule
+
diff --git a/verilog/sd2snes/ipcore_dir/msu_databuf.xise b/verilog/sd2snes/ipcore_dir/msu_databuf.xise
new file mode 100644
index 0000000..39ae055
--- /dev/null
+++ b/verilog/sd2snes/ipcore_dir/msu_databuf.xise
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes/main.v b/verilog/sd2snes/main.v
index 4df4f09..fac4ee3 100644
--- a/verilog/sd2snes/main.v
+++ b/verilog/sd2snes/main.v
@@ -79,6 +79,22 @@ wire [3:0] MAPPER;
wire [23:0] SAVERAM_MASK;
wire [23:0] ROM_MASK;
wire [7:0] SD_DMA_SRAM_DATA;
+wire [1:0] SD_DMA_TGT;
+wire [10:0] SD_DMA_PARTIAL_START;
+wire [10:0] SD_DMA_PARTIAL_END;
+
+wire [10:0] dac_addr;
+//wire [7:0] dac_volume;
+wire [7:0] msu_volumerq_out;
+wire [6:0] msu_status_out;
+wire [31:0] msu_addressrq_out;
+wire [15:0] msu_trackrq_out;
+wire [13:0] msu_addr;
+wire [7:0] MSU_SNES_DATA_IN;
+wire [7:0] MSU_SNES_DATA_OUT;
+wire [5:0] msu_status_reset_bits;
+wire [5:0] msu_status_set_bits;
+
//wire SD_DMA_EN; //SPI_DMA_CTRL;
sd_dma snes_sd_dma(.CLK(CLK2),
@@ -88,15 +104,48 @@ sd_dma snes_sd_dma(.CLK(CLK2),
.SD_DMA_STATUS(SD_DMA_STATUS),
.SD_DMA_SRAM_WE(SD_DMA_SRAM_WE),
.SD_DMA_SRAM_DATA(SD_DMA_SRAM_DATA),
- .SD_DMA_NEXTADDR(SD_DMA_NEXTADDR)
+ .SD_DMA_NEXTADDR(SD_DMA_NEXTADDR),
+ .SD_DMA_TGT(SD_DMA_TGT),
+ .SD_DMA_PARTIAL(SD_DMA_PARTIAL),
+ .SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START),
+ .SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END)
);
dac_test snes_dac_test(.clkin(CLK2),
.mclk(DAC_MCLK),
.lrck(DAC_LRCK),
- .sdout(DAC_SDOUT)
+ .sdout(DAC_SDOUT),
+ .we(SD_DMA_TGT==2'b01 ? SD_DMA_SRAM_WE : 1'b1),
+ .pgm_address(dac_addr),
+ .pgm_data(SD_DMA_SRAM_DATA),
+ .DAC_STATUS(DAC_STATUS),
+ .volume(msu_volumerq_out),
+ .vol_latch(msu_volume_latch_out),
+ .play(dac_play),
+ .reset(dac_reset)
);
-
+
+msu snes_msu (
+ .clkin(CLK2),
+ .enable(msu_enable),
+ .pgm_address(msu_addr),
+ .pgm_data(SD_DMA_SRAM_DATA),
+ .pgm_we(SD_DMA_TGT==2'b10 ? SD_DMA_SRAM_WE : 1'b1),
+ .reg_addr(SNES_ADDR),
+ .reg_data_in(MSU_SNES_DATA_IN),
+ .reg_data_out(MSU_SNES_DATA_OUT),
+ .reg_oe(SNES_READ),
+ .reg_we(SNES_WRITE),
+ .status_out(msu_status_out),
+ .volume_out(msu_volumerq_out),
+ .volume_latch_out(msu_volume_latch_out),
+ .addr_out(msu_addressrq_out),
+ .track_out(msu_trackrq_out),
+ .status_reset_bits(msu_status_reset_bits),
+ .status_set_bits(msu_status_set_bits),
+ .status_reset_we(msu_status_reset_we)
+ );
+
spi snes_spi(.clk(CLK2),
.MOSI(SPI_MOSI),
.MISO(SPI_MISO),
@@ -137,7 +186,25 @@ mcu_cmd snes_mcu_cmd(
.SD_DMA_STATUS(SD_DMA_STATUS),
.SD_DMA_NEXTADDR(SD_DMA_NEXTADDR),
.SD_DMA_SRAM_DATA(SD_DMA_SRAM_DATA),
- .SD_DMA_SRAM_WE(SD_DMA_SRAM_WE)
+ .SD_DMA_SRAM_WE(SD_DMA_SRAM_WE),
+ .SD_DMA_TGT(SD_DMA_TGT),
+ .SD_DMA_PARTIAL(SD_DMA_PARTIAL),
+ .SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START),
+ .SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END),
+ .dac_addr_out(dac_addr),
+ .DAC_STATUS(DAC_STATUS),
+// .dac_volume_out(dac_volume),
+// .dac_volume_latch_out(dac_vol_latch),
+ .dac_play_out(dac_play),
+ .dac_reset_out(dac_reset),
+ .msu_addr_out(msu_addr),
+ .MSU_STATUS(msu_status_out),
+ .msu_status_reset_out(msu_status_reset_bits),
+ .msu_status_set_out(msu_status_set_bits),
+ .msu_status_reset_we(msu_status_reset_we),
+ .msu_volumerq(msu_volumerq_out),
+ .msu_addressrq(msu_addressrq_out),
+ .msu_trackrq(msu_trackrq_out)
);
// dcm1: dfs 4x
@@ -238,7 +305,10 @@ address snes_addr(
.MCU_ADDR(MCU_ADDR),
.ROM_ADDR0(ROM_ADDR0),
.SAVERAM_MASK(SAVERAM_MASK),
- .ROM_MASK(ROM_MASK)
+ .ROM_MASK(ROM_MASK),
+ //MSU-1
+ .use_msu(use_msu),
+ .msu_enable(msu_enable)
);
wire SNES_READ_CYCLEw;
@@ -261,7 +331,10 @@ data snes_data(.CLK(CLK2),
.MCU_OVR(MCU_OVR),
.MCU_IN_DATA(MCU_IN_DATA),
.MCU_OUT_DATA(MCU_OUT_DATA),
- .ROM_ADDR0(ROM_ADDR0)
+ .ROM_ADDR0(ROM_ADDR0),
+ .MSU_DATA_IN(MSU_SNES_DATA_IN),
+ .MSU_DATA_OUT(MSU_SNES_DATA_OUT),
+ .msu_enable(msu_enable)
);
parameter MODE_SNES = 1'b0;
@@ -497,7 +570,7 @@ assign ROM_BLE = !ROM_WE ? !ROM_ADDR0 : 1'b0;
//assign SRAM_WE = !MCU_ENA ? MCU_WRITE : 1'b1;
//assign SNES_DATABUS_OE = (!IS_SAVERAM & SNES_CS) | (SNES_READ & SNES_WRITE);
-assign SNES_DATABUS_OE = (IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM) | (SNES_READ & SNES_WRITE);
+assign SNES_DATABUS_OE = msu_enable ? 1'b0 : ((IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM) | (SNES_READ & SNES_WRITE));
assign SNES_DATABUS_DIR = !SNES_READ ? 1'b1 : 1'b0;
assign SNES_DATA_TO_MEM = SNES_DATA_TO_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX];
diff --git a/verilog/sd2snes/msu.v b/verilog/sd2snes/msu.v
new file mode 100644
index 0000000..26a2eab
--- /dev/null
+++ b/verilog/sd2snes/msu.v
@@ -0,0 +1,174 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 14:55:04 12/14/2010
+// Design Name:
+// Module Name: msu
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module msu(
+ input clkin,
+ input enable,
+ input [13:0] pgm_address,
+ input [7:0] pgm_data,
+ input pgm_we,
+ input [2:0] reg_addr,
+ input [7:0] reg_data_in,
+ output [7:0] reg_data_out,
+ input reg_oe,
+ input reg_we,
+ output [6:0] status_out,
+ output [7:0] volume_out,
+ output volume_latch_out,
+ output [31:0] addr_out,
+ output [15:0] track_out,
+ input [5:0] status_reset_bits,
+ input [5:0] status_set_bits,
+ input status_reset_we
+ );
+
+reg [1:0] status_reset_we_r;
+always @(posedge clkin) status_reset_we_r = {status_reset_we_r[0], status_reset_we};
+wire status_reset_en = (status_reset_we_r == 2'b01);
+
+reg [13:0] msu_address_r;
+wire [13:0] msu_address = msu_address_r;
+
+wire [7:0] msu_data;
+reg [7:0] msu_data_r;
+
+reg [5:0] reg_oe_sreg;
+always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[4:0], reg_oe};
+wire reg_oe_falling = (reg_oe_sreg[5:0] == 6'b111110);
+wire reg_oe_rising = (reg_oe_sreg[5:0] == 6'b000001);
+
+reg [1:0] reg_we_sreg;
+always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[0], reg_we};
+wire reg_we_rising = (reg_we_sreg[1:0] == 2'b01);
+
+reg [31:0] addr_out_r;
+assign addr_out = addr_out_r;
+
+reg [15:0] track_out_r;
+assign track_out = track_out_r;
+
+reg [7:0] volume_r;
+assign volume_out = volume_r;
+
+reg volume_start_r;
+assign volume_latch_out = volume_start_r;
+
+reg audio_start_r;
+reg audio_busy_r;
+reg data_start_r;
+reg data_busy_r;
+reg ctrl_start_r;
+reg [1:0] audio_ctrl_r;
+reg [1:0] audio_status_r;
+
+initial begin
+ audio_busy_r <= 1'b1;
+ data_busy_r <= 1'b1;
+end
+
+assign status_out = {msu_address_r[13],
+ audio_start_r, data_start_r, volume_start_r, audio_ctrl_r, ctrl_start_r};
+
+initial msu_address_r = 14'h0000;
+
+msu_databuf snes_msu_databuf (
+ .clka(clkin),
+ .wea(~pgm_we), // Bus [0 : 0]
+ .addra(pgm_address), // Bus [13 : 0]
+ .dina(pgm_data), // Bus [7 : 0]
+ .clkb(clkin),
+ .addrb(msu_address), // Bus [13 : 0]
+ .doutb(msu_data)); // Bus [7 : 0]
+
+reg [7:0] msu_regs [7:0];
+
+reg [7:0] data_out_r;
+reg [7:0] data_in_r;
+assign reg_data_out = data_out_r;
+always @(posedge clkin) data_in_r <= reg_data_in;
+
+always @(posedge clkin) begin
+ case(reg_addr)
+ 3'h0: data_out_r <= {data_busy_r, audio_busy_r, audio_status_r, 4'b0001};
+ 3'h1: data_out_r <= msu_data_r;
+ 3'h2: data_out_r <= 8'h53;
+ 3'h3: data_out_r <= 8'h2d;
+ 3'h4: data_out_r <= 8'h4d;
+ 3'h5: data_out_r <= 8'h53;
+ 3'h6: data_out_r <= 8'h55;
+ 3'h7: data_out_r <= 8'h31;
+ endcase
+end
+
+always @(posedge clkin) begin
+ if(reg_we_rising && enable) begin
+ case(reg_addr)
+ 3'h0: addr_out_r[7:0] <= reg_data_in;
+ 3'h1: addr_out_r[15:8] <= reg_data_in;
+ 3'h2: addr_out_r[23:16] <= reg_data_in;
+ 3'h3: begin
+ addr_out_r[31:24] <= reg_data_in;
+ data_start_r <= 1'b1;
+ data_busy_r <= 1'b1;
+ end
+ 3'h4: begin
+ track_out_r[7:0] <= reg_data_in;
+ end
+ 3'h5: begin
+ track_out_r[15:8] <= reg_data_in;
+ audio_start_r <= 1'b1;
+ audio_busy_r <= 1'b1;
+ end
+ 3'h6: begin
+ volume_r <= reg_data_in;
+ volume_start_r <= 1'b1;
+ end
+ 3'h7: begin
+ if(!audio_busy_r) begin
+ audio_ctrl_r <= reg_data_in[1:0];
+ ctrl_start_r <= 1'b1;
+ end
+ end
+ endcase
+ end else if (status_reset_en) begin
+ audio_busy_r <= (audio_busy_r | status_set_bits[5]) & ~status_reset_bits[5];
+ if(status_reset_bits[5]) audio_start_r <= 1'b0;
+
+ data_busy_r <= (data_busy_r | status_set_bits[4]) & ~status_reset_bits[4];
+ if(status_reset_bits[4]) data_start_r <= 1'b0;
+
+// volume_start_r <= (volume_start_r | status_set_bits[3]) & ~status_reset_bits[3];
+
+ audio_status_r <= (audio_status_r | status_set_bits[2:1]) & ~status_reset_bits[2:1];
+
+ ctrl_start_r <= (ctrl_start_r | status_set_bits[0]) & ~status_reset_bits[0];
+ end else begin
+ volume_start_r <= 1'b0;
+ end
+end
+
+always @(posedge clkin) begin
+ if(reg_oe_falling && enable && reg_addr == 3'h1) begin
+ msu_address_r <= msu_address_r + 1;
+ msu_data_r <= msu_data;
+ end
+end
+
+endmodule
diff --git a/verilog/sd2snes/sd2snes.xise b/verilog/sd2snes/sd2snes.xise
index dae01e0..c777896 100644
--- a/verilog/sd2snes/sd2snes.xise
+++ b/verilog/sd2snes/sd2snes.xise
@@ -50,6 +50,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes/sd_dma.v b/verilog/sd2snes/sd_dma.v
index 3e8b4bc..0f0397a 100644
--- a/verilog/sd2snes/sd_dma.v
+++ b/verilog/sd2snes/sd_dma.v
@@ -23,12 +23,21 @@ module sd_dma(
inout SD_CLK,
input CLK,
input SD_DMA_EN,
+ input SD_DMA_TGT,
output SD_DMA_STATUS,
output SD_DMA_SRAM_WE,
output SD_DMA_NEXTADDR,
- output [7:0] SD_DMA_SRAM_DATA
+ output [7:0] SD_DMA_SRAM_DATA,
+ input SD_DMA_PARTIAL,
+ input [10:0] SD_DMA_PARTIAL_START,
+ input [10:0] SD_DMA_PARTIAL_END
);
+reg [10:0] SD_DMA_STARTr;
+reg [10:0] SD_DMA_ENDr;
+reg SD_DMA_PARTIALr;
+always @(posedge CLK) SD_DMA_PARTIALr <= SD_DMA_PARTIAL;
+
reg SD_DMA_DONEr;
reg[2:0] SD_DMA_DONEr2;
initial begin
@@ -36,7 +45,7 @@ initial begin
SD_DMA_DONEr = 1'b0;
end
always @(posedge CLK) SD_DMA_DONEr2 <= {SD_DMA_DONEr2[1:0], SD_DMA_DONEr};
-wire SD_DMA_DONE_rising = (SD_DMA_DONEr2 == 2'b01);
+wire SD_DMA_DONE_rising = (SD_DMA_DONEr2[1:0] == 2'b01);
reg [2:0] SD_DMA_ENr;
initial SD_DMA_ENr = 3'b000;
@@ -67,7 +76,11 @@ always @(posedge CLK) SD_CLKr <= clkcnt[1];
assign SD_CLK = SD_DMA_STATUSr ? SD_CLKr : 1'bZ;
always @(posedge CLK) begin
- if(SD_DMA_EN_rising) SD_DMA_STATUSr <= 1'b1;
+ if(SD_DMA_EN_rising) begin
+ SD_DMA_STATUSr <= 1'b1;
+ SD_DMA_STARTr <= (SD_DMA_PARTIALr ? SD_DMA_PARTIAL_START : 11'h0);
+ SD_DMA_ENDr <= (SD_DMA_PARTIALr ? SD_DMA_PARTIAL_END : 11'd1024);
+ end
else if (SD_DMA_DONE_rising) SD_DMA_STATUSr <= 1'b0;
end
@@ -77,7 +90,7 @@ always @(posedge CLK) begin
end
always @(posedge CLK) begin
- if(SD_DMA_EN_rising) begin
+ if(SD_DMA_EN_rising || !SD_DMA_STATUSr) begin
clkcnt <= 0;
end else begin
if(SD_DMA_STATUSr) begin
@@ -87,7 +100,7 @@ always @(posedge CLK) begin
end
always @(posedge CLK) begin
- if(SD_DMA_EN_rising) cyclecnt <= 0;
+ if(SD_DMA_EN_rising || !SD_DMA_STATUSr) cyclecnt <= 0;
else if(clkcnt[1:0] == 2'b11) cyclecnt <= cyclecnt + 1;
end
@@ -99,13 +112,13 @@ always @(posedge CLK) begin
3'h0: begin
SD_DMA_SRAM_WEr <= 1'b1;
SD_DMA_SRAM_DATAr[7:4] <= SD_DAT;
- if(cyclecnt>0 && cyclecnt < 1025) SD_DMA_NEXTADDRr <= 1'b1;
+ if(cyclecnt>SD_DMA_STARTr && cyclecnt <= SD_DMA_ENDr) SD_DMA_NEXTADDRr <= 1'b1;
end
3'h1:
SD_DMA_NEXTADDRr <= 1'b0;
// 3'h2:
3'h3:
- SD_DMA_SRAM_WEr <= 1'b0;
+ if(cyclecnt>=SD_DMA_STARTr && cyclecnt <= SD_DMA_ENDr) SD_DMA_SRAM_WEr <= 1'b0;
3'h4:
SD_DMA_SRAM_DATAr[3:0] <= SD_DAT;
// 3'h5: