diff --git a/verilog/sd2snes_test/address.v b/verilog/sd2snes_test/address.v
new file mode 100644
index 0000000..6dae255
--- /dev/null
+++ b/verilog/sd2snes_test/address.v
@@ -0,0 +1,72 @@
+`timescale 1 ns / 1 ns
+//////////////////////////////////////////////////////////////////////////////////
+// Company: Rehkopf
+// Engineer: Rehkopf
+//
+// Create Date: 01:13:46 05/09/2009
+// Design Name:
+// Module Name: address
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description: Address logic w/ SaveRAM masking
+//
+// Dependencies:
+//
+// Revision:
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module address(
+ input CLK,
+ input [23:0] SNES_ADDR, // requested address from SNES
+ output [23:0] ram0_addr,
+ output [18:0] ram1_addr,
+ output [7:0] PA_addr,
+ output [12:0] bram_addr,
+ input [7:0] ram0_bank,
+ input ram0_linear,
+ output ram0_enable,
+ output ram1_enable,
+ output PA_enable,
+ output bram_enable,
+ output irq_enable,
+ output bank_enable,
+ output linear_enable
+);
+
+wire [23:0] SRAM_SNES_ADDR;
+
+assign ram0bank0_enable = (SNES_ADDR[23:15] == 9'h001) | (SNES_ADDR[23:16] == 8'hC0);
+assign ram0bankx_enable = (SNES_ADDR[23:16] == 8'hC8);
+assign ram0linear_enable = ram0_linear & (SNES_ADDR[22] | SNES_ADDR[15]);
+assign ram0_enable = ram0linear_enable | ram0bank0_enable | ram0bankx_enable;
+assign ram1_enable = ~ram0_enable & (SNES_ADDR[23:20] == 4'hD);
+assign PA_enable = ~ram0_enable & (SNES_ADDR[23:20] == 4'hE);
+assign bram_enable = ~ram0_enable & (SNES_ADDR[23:20] == 4'hF);
+wire bank_enable_ = (SNES_ADDR == 24'h0055AA);
+wire irq_enable_ = (SNES_ADDR == 24'h002222);
+wire linear_enable_ = (SNES_ADDR == 24'h003333);
+
+reg [2:0] bank_enable_r;
+reg [2:0] irq_enable_r;
+reg [2:0] linear_enable_r;
+always @(posedge CLK) begin
+ bank_enable_r <= {bank_enable_r[1:0], bank_enable_};
+ irq_enable_r <= {irq_enable_r[1:0], irq_enable_};
+ linear_enable_r <= {linear_enable_r[1:0], linear_enable_};
+end
+assign bank_enable = bank_enable_r[2];
+assign irq_enable = irq_enable_r[2];
+assign linear_enable = linear_enable_r[2];
+
+assign ram0_addr = ram0_linear ? SNES_ADDR
+ : {2'b00,SNES_ADDR[21:0]};
+
+assign ram1_addr = SNES_ADDR[18:0];
+
+assign PA_addr = SNES_ADDR[7:0];
+
+assign bram_addr = SNES_ADDR[12:0];
+
+endmodule
diff --git a/verilog/sd2snes_test/clk_test.v b/verilog/sd2snes_test/clk_test.v
new file mode 100644
index 0000000..d00601d
--- /dev/null
+++ b/verilog/sd2snes_test/clk_test.v
@@ -0,0 +1,120 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 22:40:46 12/20/2010
+// Design Name:
+// Module Name: clk_test
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module clk_test(
+ input clk,
+ input sysclk,
+ input read,
+ input write,
+ input pawr,
+ input pard,
+ input refresh,
+ input cpuclk,
+ input romsel,
+ output reg [31:0] snes_sysclk_freq,
+ output reg [31:0] snes_read_freq,
+ output reg [31:0] snes_write_freq,
+ output reg [31:0] snes_pawr_freq,
+ output reg [31:0] snes_pard_freq,
+ output reg [31:0] snes_refresh_freq,
+ output reg [31:0] snes_cpuclk_freq,
+ output reg [31:0] snes_romsel_freq
+);
+
+reg [31:0] sysclk_counter;
+reg [31:0] sysclk_value;
+reg [31:0] read_value;
+reg [31:0] write_value;
+reg [31:0] pard_value;
+reg [31:0] pawr_value;
+reg [31:0] refresh_value;
+reg [31:0] cpuclk_value;
+reg [31:0] romsel_value;
+
+initial snes_sysclk_freq = 32'hFFFFFFFF;
+initial sysclk_counter = 0;
+initial sysclk_value = 0;
+initial read_value = 0;
+initial write_value = 0;
+initial pard_value = 0;
+initial pawr_value = 0;
+initial refresh_value = 0;
+initial cpuclk_value = 0;
+initial romsel_value = 0;
+
+reg [1:0] sysclk_sreg;
+reg [1:0] read_sreg;
+reg [1:0] write_sreg;
+reg [1:0] pard_sreg;
+reg [1:0] pawr_sreg;
+reg [1:0] refresh_sreg;
+reg [1:0] cpuclk_sreg;
+reg [1:0] romsel_sreg;
+
+always @(posedge clk) romsel_sreg <= {romsel_sreg[0], romsel};
+wire romsel_rising = (romsel_sreg == 2'b01);
+always @(posedge clk) cpuclk_sreg <= {cpuclk_sreg[0], cpuclk};
+wire cpuclk_rising = (cpuclk_sreg == 2'b01);
+always @(posedge clk) sysclk_sreg <= {sysclk_sreg[0], sysclk};
+wire sysclk_rising = (sysclk_sreg == 2'b01);
+always @(posedge clk) read_sreg <= {read_sreg[0], read};
+wire read_rising = (read_sreg == 2'b01);
+always @(posedge clk) write_sreg <= {write_sreg[0], write};
+wire write_rising = (write_sreg == 2'b01);
+always @(posedge clk) pard_sreg <= {pard_sreg[0], pard};
+wire pard_rising = (pard_sreg == 2'b01);
+always @(posedge clk) pawr_sreg <= {pawr_sreg[0], pawr};
+wire pawr_rising = (pawr_sreg == 2'b01);
+always @(posedge clk) refresh_sreg <= {refresh_sreg[0], refresh};
+wire refresh_rising = (refresh_sreg == 2'b01);
+
+always @(posedge clk) begin
+ if(sysclk_counter < 96000000) begin
+ sysclk_counter <= sysclk_counter + 1;
+ if(sysclk_rising) sysclk_value <= sysclk_value + 1;
+ if(read_rising) read_value <= read_value + 1;
+ if(write_rising) write_value <= write_value + 1;
+ if(pard_rising) pard_value <= pard_value + 1;
+ if(pawr_rising) pawr_value <= pawr_value + 1;
+ if(refresh_rising) refresh_value <= refresh_value + 1;
+ if(cpuclk_rising) cpuclk_value <= cpuclk_value + 1;
+ if(romsel_rising) romsel_value <= romsel_value + 1;
+ end else begin
+ snes_sysclk_freq <= sysclk_value;
+ snes_read_freq <= read_value;
+ snes_write_freq <= write_value;
+ snes_pard_freq <= pard_value;
+ snes_pawr_freq <= pawr_value;
+ snes_refresh_freq <= refresh_value;
+ snes_cpuclk_freq <= cpuclk_value;
+ snes_romsel_freq <= romsel_value;
+ sysclk_counter <= 0;
+ sysclk_value <= 0;
+ read_value <= 0;
+ write_value <= 0;
+ pard_value <= 0;
+ pawr_value <= 0;
+ refresh_value <= 0;
+ cpuclk_value <= 0;
+ romsel_value <= 0;
+ end
+end
+
+endmodule
diff --git a/verilog/sd2snes_test/dac.v b/verilog/sd2snes_test/dac.v
new file mode 100644
index 0000000..db6d059
--- /dev/null
+++ b/verilog/sd2snes_test/dac.v
@@ -0,0 +1,146 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 19:26:11 07/23/2010
+// Design Name:
+// Module Name: dac_test
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module dac(
+ input clkin,
+ input sysclk,
+ input we,
+ input[10:0] pgm_address,
+ input[7:0] pgm_data,
+ input play,
+ input reset,
+ output sdout,
+ output lrck,
+ output mclk,
+ output DAC_STATUS
+);
+
+reg[8:0] dac_address_r;
+wire[8:0] dac_address = dac_address_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;
+reg[2:0] sysclk_sreg;
+wire sysclk_rising = (sysclk_sreg[2:1] == 2'b01);
+
+reg [25:0] interpol_count;
+
+always @(posedge clkin) begin
+ sysclk_sreg <= {sysclk_sreg[1:0], sysclk};
+end
+
+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 [8 : 0]
+ .doutb(dac_data)); // Bus [31 : 0]
+
+reg [8:0] cnt;
+reg [15:0] smpcnt;
+reg [1:0] samples;
+reg [15:0] smpshift;
+
+assign mclk = cnt[2]; // mclk = clk/8
+assign lrck = cnt[8]; // lrck = mclk/128
+wire sclk = cnt[3]; // sclk = lrck*32
+
+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[2:1]} == 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 = 9'h100;
+ smpcnt = 16'b0;
+ lrck_sreg = 2'b11;
+ sclk_sreg = 1'b0;
+ dac_address_r = 10'b0;
+ vol_valid = 1'b0;
+ vol_latch_reg = 1'b0;
+ vol_reg = 8'h0;
+ vol_target_reg = 8'hff;
+ samples <= 2'b00;
+end
+
+always @(posedge clkin) begin
+ if(reset_rising) begin
+ dac_address_r <= 0;
+ interpol_count <= 0;
+ end else if(sysclk_rising) begin
+ if(interpol_count > 59378938) begin
+ interpol_count <= interpol_count + 122500 - 59501439;
+ dac_address_r <= dac_address_r + play_r;
+ end else begin
+ interpol_count <= interpol_count + 122500;
+ end
+ end
+end
+
+always @(posedge clkin) begin
+ cnt <= cnt + 1;
+ lrck_sreg <= {lrck_sreg[1:0], lrck};
+ sclk_sreg <= {sclk_sreg[1:0], sclk};
+ play_r <= play;
+ reset_sreg <= {reset_sreg[0], reset};
+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, dac_data[31:16]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
+ samples <= samples + 1;
+ end else if (lrck_falling) begin // left channel
+ smpshift <= (({16'h0, dac_data[15:0]^16'h8000} * vol_reg) >> 8) ^ 16'h8000;
+ end else begin
+ if (sclk_rising) begin
+ smpcnt <= smpcnt + 1;
+ sdout_reg <= smpshift[15];
+ smpshift <= {smpshift[14:0], 1'b0};
+ end
+ end
+end
+
+endmodule
diff --git a/verilog/sd2snes_test/dcm.v b/verilog/sd2snes_test/dcm.v
new file mode 100644
index 0000000..90b516e
--- /dev/null
+++ b/verilog/sd2snes_test/dcm.v
@@ -0,0 +1,72 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 13:06:52 06/28/2009
+// Design Name:
+// Module Name: dcm
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module my_dcm (
+ input CLKIN,
+ output CLKFX,
+ output LOCKED,
+ input RST,
+ output[7:0] STATUS
+ );
+
+ // DCM: Digital Clock Manager Circuit
+ // Spartan-3
+ // Xilinx HDL Language Template, version 11.1
+
+ DCM #(
+ .SIM_MODE("SAFE"), // Simulation: "SAFE" vs. "FAST", see "Synthesis and Simulation Design Guide" for details
+ .CLKDV_DIVIDE(2.0), // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
+ // 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
+ .CLKFX_DIVIDE(1), // Can be any integer from 1 to 32
+ .CLKFX_MULTIPLY(4), // Can be any integer from 2 to 32
+ .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
+ .CLKIN_PERIOD(41.667), // Specify period of input clock
+ .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE
+ .CLK_FEEDBACK("NONE"), // Specify clock feedback of NONE, 1X or 2X
+ .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
+ // an integer from 0 to 15
+ .DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis
+ .DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL
+ .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
+ .FACTORY_JF(16'hFFFF), // FACTORY JF values
+// .LOC("DCM_X0Y0"),
+ .PHASE_SHIFT(0), // Amount of fixed phase shift from -255 to 255
+ .STARTUP_WAIT("TRUE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE
+ ) DCM_inst (
+ .CLK0(CLK0), // 0 degree DCM CLK output
+ .CLK180(CLK180), // 180 degree DCM CLK output
+ .CLK270(CLK270), // 270 degree DCM CLK output
+ .CLK2X(CLK2X), // 2X DCM CLK output
+ .CLK2X180(CLK2X180), // 2X, 180 degree DCM CLK out
+ .CLK90(CLK90), // 90 degree DCM CLK output
+ .CLKDV(CLKDV), // Divided DCM CLK out (CLKDV_DIVIDE)
+ .CLKFX(CLKFX), // DCM CLK synthesis out (M/D)
+ .CLKFX180(CLKFX180), // 180 degree CLK synthesis out
+ .LOCKED(LOCKED), // DCM LOCK status output
+ .PSDONE(PSDONE), // Dynamic phase adjust done output
+ .STATUS(STATUS), // 8-bit DCM status bits output
+ .CLKFB(CLKFB), // DCM clock feedback
+ .CLKIN(CLKIN), // Clock input (from IBUFG, BUFG or DCM)
+ .PSCLK(PSCLK), // Dynamic phase adjust clock input
+ .PSEN(PSEN), // Dynamic phase adjust enable input
+ .PSINCDEC(PSINCDEC), // Dynamic phase adjust increment/decrement
+ .RST(RST) // DCM asynchronous reset input
+ );
+endmodule
diff --git a/verilog/sd2snes_test/ipcore_dir/PA.xco b/verilog/sd2snes_test/ipcore_dir/PA.xco
new file mode 100644
index 0000000..e25d689
--- /dev/null
+++ b/verilog/sd2snes_test/ipcore_dir/PA.xco
@@ -0,0 +1,105 @@
+##############################################################
+#
+# Xilinx Core Generator version 13.2
+# Date: Fri Dec 9 20:36:25 2011
+#
+##############################################################
+#
+# This file contains the customisation parameters for a
+# Xilinx CORE Generator IP GUI. It is strongly recommended
+# that you do not manually alter this file as it may cause
+# unexpected and unsupported behavior.
+#
+##############################################################
+#
+# Generated from component: xilinx.com:ip:blk_mem_gen:6.2
+#
+##############################################################
+#
+# BEGIN Project Options
+SET addpads = false
+SET asysymbol = true
+SET busformat = BusFormatAngleBracketNotRipped
+SET createndf = false
+SET designentry = Verilog
+SET device = xa3s400
+SET devicefamily = aspartan3
+SET flowvendor = Other
+SET formalverification = false
+SET foundationsym = false
+SET implementationfiletype = Ngc
+SET package = pqg208
+SET removerpms = false
+SET simulationfiles = Behavioral
+SET speedgrade = -4q
+SET verilogsim = true
+SET vhdlsim = false
+# END Project Options
+# BEGIN Select
+SELECT Block_Memory_Generator xilinx.com:ip:blk_mem_gen:6.2
+# END Select
+# BEGIN Parameters
+CSET additional_inputs_for_power_estimation=false
+CSET algorithm=Minimum_Area
+CSET assume_synchronous_clk=true
+CSET axi_id_width=4
+CSET axi_slave_type=Memory_Slave
+CSET axi_type=AXI4_Full
+CSET byte_size=9
+CSET coe_file=no_coe_file_loaded
+CSET collision_warnings=ALL
+CSET component_name=PA
+CSET disable_collision_warnings=false
+CSET disable_out_of_range_warnings=false
+CSET ecc=false
+CSET ecctype=No_ECC
+CSET enable_a=Always_Enabled
+CSET enable_b=Always_Enabled
+CSET error_injection_type=Single_Bit_Error_Injection
+CSET fill_remaining_memory_locations=false
+CSET interface_type=Native
+CSET load_init_file=false
+CSET memory_type=Simple_Dual_Port_RAM
+CSET operating_mode_a=WRITE_FIRST
+CSET operating_mode_b=WRITE_FIRST
+CSET output_reset_value_a=0
+CSET output_reset_value_b=0
+CSET pipeline_stages=0
+CSET port_a_clock=100
+CSET port_a_enable_rate=100
+CSET port_a_write_rate=50
+CSET port_b_clock=100
+CSET port_b_enable_rate=100
+CSET port_b_write_rate=0
+CSET primitive=8kx2
+CSET read_width_a=8
+CSET read_width_b=8
+CSET register_porta_input_of_softecc=false
+CSET register_porta_output_of_memory_core=false
+CSET register_porta_output_of_memory_primitives=false
+CSET register_portb_output_of_memory_core=false
+CSET register_portb_output_of_memory_primitives=false
+CSET register_portb_output_of_softecc=false
+CSET remaining_memory_locations=0
+CSET reset_memory_latch_a=false
+CSET reset_memory_latch_b=false
+CSET reset_priority_a=CE
+CSET reset_priority_b=CE
+CSET reset_type=SYNC
+CSET softecc=false
+CSET use_axi_id=false
+CSET use_byte_write_enable=false
+CSET use_error_injection_pins=false
+CSET use_regcea_pin=false
+CSET use_regceb_pin=false
+CSET use_rsta_pin=false
+CSET use_rstb_pin=false
+CSET write_depth_a=256
+CSET write_width_a=8
+CSET write_width_b=8
+# END Parameters
+# BEGIN Extra information
+MISC pkg_timestamp=2011-03-11T08:24:14.000Z
+# END Extra information
+GENERATE
+# CRC: 213d12c4
diff --git a/verilog/sd2snes_test/ipcore_dir/PA.xise b/verilog/sd2snes_test/ipcore_dir/PA.xise
new file mode 100644
index 0000000..33142d2
--- /dev/null
+++ b/verilog/sd2snes_test/ipcore_dir/PA.xise
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes_test/ipcore_dir/bram.xco b/verilog/sd2snes_test/ipcore_dir/bram.xco
new file mode 100644
index 0000000..4312d26
--- /dev/null
+++ b/verilog/sd2snes_test/ipcore_dir/bram.xco
@@ -0,0 +1,105 @@
+##############################################################
+#
+# Xilinx Core Generator version 13.2
+# Date: Fri Dec 9 20:35:22 2011
+#
+##############################################################
+#
+# This file contains the customisation parameters for a
+# Xilinx CORE Generator IP GUI. It is strongly recommended
+# that you do not manually alter this file as it may cause
+# unexpected and unsupported behavior.
+#
+##############################################################
+#
+# Generated from component: xilinx.com:ip:blk_mem_gen:6.2
+#
+##############################################################
+#
+# BEGIN Project Options
+SET addpads = false
+SET asysymbol = true
+SET busformat = BusFormatAngleBracketNotRipped
+SET createndf = false
+SET designentry = Verilog
+SET device = xa3s400
+SET devicefamily = aspartan3
+SET flowvendor = Other
+SET formalverification = false
+SET foundationsym = false
+SET implementationfiletype = Ngc
+SET package = pqg208
+SET removerpms = false
+SET simulationfiles = Behavioral
+SET speedgrade = -4q
+SET verilogsim = true
+SET vhdlsim = false
+# END Project Options
+# BEGIN Select
+SELECT Block_Memory_Generator xilinx.com:ip:blk_mem_gen:6.2
+# END Select
+# BEGIN Parameters
+CSET additional_inputs_for_power_estimation=false
+CSET algorithm=Minimum_Area
+CSET assume_synchronous_clk=true
+CSET axi_id_width=4
+CSET axi_slave_type=Memory_Slave
+CSET axi_type=AXI4_Full
+CSET byte_size=9
+CSET coe_file=no_coe_file_loaded
+CSET collision_warnings=ALL
+CSET component_name=bram
+CSET disable_collision_warnings=false
+CSET disable_out_of_range_warnings=false
+CSET ecc=false
+CSET ecctype=No_ECC
+CSET enable_a=Always_Enabled
+CSET enable_b=Always_Enabled
+CSET error_injection_type=Single_Bit_Error_Injection
+CSET fill_remaining_memory_locations=false
+CSET interface_type=Native
+CSET load_init_file=false
+CSET memory_type=True_Dual_Port_RAM
+CSET operating_mode_a=WRITE_FIRST
+CSET operating_mode_b=WRITE_FIRST
+CSET output_reset_value_a=0
+CSET output_reset_value_b=0
+CSET pipeline_stages=0
+CSET port_a_clock=100
+CSET port_a_enable_rate=100
+CSET port_a_write_rate=50
+CSET port_b_clock=100
+CSET port_b_enable_rate=100
+CSET port_b_write_rate=50
+CSET primitive=8kx2
+CSET read_width_a=8
+CSET read_width_b=8
+CSET register_porta_input_of_softecc=false
+CSET register_porta_output_of_memory_core=false
+CSET register_porta_output_of_memory_primitives=false
+CSET register_portb_output_of_memory_core=false
+CSET register_portb_output_of_memory_primitives=false
+CSET register_portb_output_of_softecc=false
+CSET remaining_memory_locations=0
+CSET reset_memory_latch_a=false
+CSET reset_memory_latch_b=false
+CSET reset_priority_a=CE
+CSET reset_priority_b=CE
+CSET reset_type=SYNC
+CSET softecc=false
+CSET use_axi_id=false
+CSET use_byte_write_enable=false
+CSET use_error_injection_pins=false
+CSET use_regcea_pin=false
+CSET use_regceb_pin=false
+CSET use_rsta_pin=false
+CSET use_rstb_pin=false
+CSET write_depth_a=8192
+CSET write_width_a=8
+CSET write_width_b=8
+# END Parameters
+# BEGIN Extra information
+MISC pkg_timestamp=2011-03-11T08:24:14.000Z
+# END Extra information
+GENERATE
+# CRC: cb4729a5
diff --git a/verilog/sd2snes_test/ipcore_dir/bram.xise b/verilog/sd2snes_test/ipcore_dir/bram.xise
new file mode 100644
index 0000000..8bf0faa
--- /dev/null
+++ b/verilog/sd2snes_test/ipcore_dir/bram.xise
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes_test/ipcore_dir/dac_buf.xco b/verilog/sd2snes_test/ipcore_dir/dac_buf.xco
new file mode 100644
index 0000000..316029b
--- /dev/null
+++ b/verilog/sd2snes_test/ipcore_dir/dac_buf.xco
@@ -0,0 +1,105 @@
+##############################################################
+#
+# Xilinx Core Generator version 13.2
+# Date: Fri Dec 9 20:37:13 2011
+#
+##############################################################
+#
+# This file contains the customisation parameters for a
+# Xilinx CORE Generator IP GUI. It is strongly recommended
+# that you do not manually alter this file as it may cause
+# unexpected and unsupported behavior.
+#
+##############################################################
+#
+# Generated from component: xilinx.com:ip:blk_mem_gen:6.1
+#
+##############################################################
+#
+# BEGIN Project Options
+SET addpads = false
+SET asysymbol = true
+SET busformat = BusFormatAngleBracketNotRipped
+SET createndf = false
+SET designentry = Verilog
+SET device = xa3s400
+SET devicefamily = aspartan3
+SET flowvendor = Foundation_ISE
+SET formalverification = false
+SET foundationsym = false
+SET implementationfiletype = Ngc
+SET package = pqg208
+SET removerpms = false
+SET simulationfiles = Behavioral
+SET speedgrade = -4q
+SET verilogsim = true
+SET vhdlsim = false
+# END Project Options
+# BEGIN Select
+SELECT Block_Memory_Generator xilinx.com:ip:blk_mem_gen:6.1
+# END Select
+# BEGIN Parameters
+CSET additional_inputs_for_power_estimation=false
+CSET algorithm=Minimum_Area
+CSET assume_synchronous_clk=true
+CSET axi_id_width=4
+CSET axi_slave_type=Memory_Slave
+CSET axi_type=AXI4_Full
+CSET byte_size=9
+CSET coe_file=no_coe_file_loaded
+CSET collision_warnings=ALL
+CSET component_name=dac_buf
+CSET disable_collision_warnings=false
+CSET disable_out_of_range_warnings=false
+CSET ecc=false
+CSET ecctype=No_ECC
+CSET enable_a=Always_Enabled
+CSET enable_b=Always_Enabled
+CSET error_injection_type=Single_Bit_Error_Injection
+CSET fill_remaining_memory_locations=false
+CSET interface_type=Native
+CSET load_init_file=false
+CSET memory_type=Simple_Dual_Port_RAM
+CSET operating_mode_a=WRITE_FIRST
+CSET operating_mode_b=WRITE_FIRST
+CSET output_reset_value_a=0
+CSET output_reset_value_b=0
+CSET pipeline_stages=0
+CSET port_a_clock=100
+CSET port_a_enable_rate=100
+CSET port_a_write_rate=50
+CSET port_b_clock=100
+CSET port_b_enable_rate=100
+CSET port_b_write_rate=0
+CSET primitive=8kx2
+CSET read_width_a=8
+CSET read_width_b=32
+CSET register_porta_input_of_softecc=false
+CSET register_porta_output_of_memory_core=false
+CSET register_porta_output_of_memory_primitives=false
+CSET register_portb_output_of_memory_core=false
+CSET register_portb_output_of_memory_primitives=false
+CSET register_portb_output_of_softecc=false
+CSET remaining_memory_locations=0
+CSET reset_memory_latch_a=false
+CSET reset_memory_latch_b=false
+CSET reset_priority_a=CE
+CSET reset_priority_b=CE
+CSET reset_type=SYNC
+CSET softecc=false
+CSET use_axi_id=false
+CSET use_byte_write_enable=false
+CSET use_error_injection_pins=false
+CSET use_regcea_pin=false
+CSET use_regceb_pin=false
+CSET use_rsta_pin=false
+CSET use_rstb_pin=false
+CSET write_depth_a=2048
+CSET write_width_a=8
+CSET write_width_b=32
+# END Parameters
+# BEGIN Extra information
+MISC pkg_timestamp=2011-06-21T06:43:52.000Z
+# END Extra information
+GENERATE
+# CRC: 360f80d1
diff --git a/verilog/sd2snes_test/ipcore_dir/dac_buf.xise b/verilog/sd2snes_test/ipcore_dir/dac_buf.xise
new file mode 100644
index 0000000..81e803a
--- /dev/null
+++ b/verilog/sd2snes_test/ipcore_dir/dac_buf.xise
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes_test/main.ucf b/verilog/sd2snes_test/main.ucf
new file mode 100644
index 0000000..e2457cb
--- /dev/null
+++ b/verilog/sd2snes_test/main.ucf
@@ -0,0 +1,635 @@
+NET "CLKIN" TNM_NET = "CLKIN";
+TIMESPEC TS_CLKIN = PERIOD "CLKIN" 24 MHz HIGH 50 %;
+//TIMESPEC TS_CLKIN = PERIOD "CLKIN" 21.5 MHz HIGH 50 %;
+
+NET "p113_out" IOSTANDARD = LVCMOS33;
+NET "p113_out" LOC = P113;
+
+NET "SPI_SCK" LOC = P71;
+NET "SPI_SCK" CLOCK_DEDICATED_ROUTE = FALSE;
+NET "SPI_SCK" TNM_NET = "SPI_SCK";
+TIMESPEC TS_SPI_SCK = PERIOD "SPI_SCK" 48MHz HIGH 50 %;
+
+NET "SPI_SCK" IOSTANDARD = LVCMOS33;
+NET "SPI_SCK" DRIVE = 8;
+NET "SPI_SCK" PULLUP;
+
+NET "SNES_CS" IOSTANDARD = LVCMOS33;
+NET "SNES_READ" IOSTANDARD = LVCMOS33;
+NET "SNES_WRITE" IOSTANDARD = LVCMOS33;
+NET "SNES_CPU_CLK" IOSTANDARD = LVCMOS33;
+NET "SNES_REFRESH" IOSTANDARD = LVCMOS33;
+
+NET "CLKIN" IOSTANDARD = LVCMOS33;
+//NET "CLKIN" PULLUP;
+NET "SPI_SS" PULLUP;
+//NET "DCM_RST" LOC = P46;
+//NET "DCM_RST" IOSTANDARD = LVCMOS33;
+NET "SNES_DATABUS_DIR" IOSTANDARD = LVCMOS33;
+NET "SNES_DATABUS_OE" IOSTANDARD = LVCMOS33;
+NET "SNES_IRQ" IOSTANDARD = LVCMOS33;
+
+NET "ROM_CE" LOC = P172;
+NET "ROM_CE" IOSTANDARD = LVCMOS33;
+NET "ROM_CE" DRIVE = 8;
+
+NET "SNES_ADDR[0]" LOC = P119;
+NET "SNES_ADDR[10]" LOC = P146;
+NET "SNES_ADDR[11]" LOC = P148;
+NET "SNES_ADDR[12]" LOC = P147;
+NET "SNES_ADDR[13]" LOC = P144;
+NET "SNES_ADDR[14]" LOC = P141;
+NET "SNES_ADDR[15]" LOC = P139;
+NET "SNES_ADDR[16]" LOC = P137;
+NET "SNES_ADDR[17]" LOC = P133;
+NET "SNES_ADDR[18]" LOC = P131;
+NET "SNES_ADDR[19]" LOC = P128;
+NET "SNES_ADDR[1]" LOC = P122;
+NET "SNES_ADDR[20]" LOC = P125;
+NET "SNES_ADDR[21]" LOC = P123;
+NET "SNES_ADDR[22]" LOC = P120;
+NET "SNES_ADDR[23]" LOC = P117;
+NET "SNES_ADDR[2]" LOC = P124;
+NET "SNES_ADDR[3]" LOC = P126;
+NET "SNES_ADDR[4]" LOC = P130;
+NET "SNES_ADDR[5]" LOC = P132;
+NET "SNES_ADDR[6]" LOC = P135;
+NET "SNES_ADDR[7]" LOC = P138;
+NET "SNES_ADDR[8]" LOC = P140;
+NET "SNES_ADDR[9]" LOC = P143;
+NET "SNES_DATA[0]" LOC = P107;
+NET "SNES_DATA[1]" LOC = P102;
+NET "SNES_DATA[2]" LOC = P100;
+NET "SNES_DATA[3]" LOC = P96;
+NET "SNES_DATA[4]" LOC = P108;
+NET "SNES_DATA[5]" LOC = P106;
+NET "SNES_DATA[6]" LOC = P101;
+NET "SNES_DATA[7]" LOC = P97;
+
+
+NET "CLKIN" LOC = P80;
+// NET "RST" LOC = P113;
+NET "MCU_OVR" LOC = P92;
+
+
+NET "MCU_OVR" IOSTANDARD = LVCMOS33;
+NET "MCU_OVR" DRIVE = 8;
+
+NET "MCU_RDY" LOC = P83;
+NET "MCU_RDY" IOSTANDARD = LVCMOS33;
+NET "MCU_RDY" DRIVE = 8;
+
+
+NET "ROM_ADDR[0]" LOC = P166;
+
+
+NET "ROM_ADDR[0]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[0]" DRIVE = 8;
+
+
+NET "ROM_ADDR[10]" LOC = P197;
+
+
+NET "ROM_ADDR[10]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[10]" DRIVE = 8;
+
+
+NET "ROM_ADDR[11]" LOC = P196;
+
+
+NET "ROM_ADDR[11]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[11]" DRIVE = 8;
+
+
+NET "ROM_ADDR[12]" LOC = P2;
+
+
+NET "ROM_ADDR[12]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[12]" DRIVE = 8;
+
+
+NET "ROM_ADDR[13]" LOC = P194;
+
+
+NET "ROM_ADDR[13]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[13]" DRIVE = 8;
+
+
+NET "ROM_ADDR[14]" LOC = P200;
+
+
+NET "ROM_ADDR[14]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[14]" DRIVE = 8;
+
+
+NET "ROM_ADDR[15]" LOC = P184;
+
+
+NET "ROM_ADDR[15]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[15]" DRIVE = 8;
+
+
+NET "ROM_ADDR[16]" LOC = P199;
+
+
+NET "ROM_ADDR[16]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[16]" DRIVE = 8;
+
+
+NET "ROM_ADDR[17]" LOC = P11;
+
+
+NET "ROM_ADDR[17]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[17]" DRIVE = 8;
+
+
+NET "ROM_ADDR[18]" LOC = P3;
+
+
+NET "ROM_ADDR[18]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[18]" DRIVE = 8;
+
+
+NET "ROM_ADDR[19]" LOC = P4;
+
+
+NET "ROM_ADDR[19]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[19]" DRIVE = 8;
+
+
+NET "ROM_ADDR[1]" LOC = P168;
+
+
+NET "ROM_ADDR[1]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[1]" DRIVE = 8;
+
+
+NET "ROM_ADDR[20]" LOC = P191;
+
+
+NET "ROM_ADDR[20]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[20]" DRIVE = 8;
+
+
+NET "ROM_ADDR[21]" LOC = P203;
+
+
+NET "ROM_ADDR[21]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[21]" DRIVE = 8;
+
+
+NET "ROM_ADDR[22]" LOC = P198;
+
+
+NET "ROM_ADDR[22]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[22]" DRIVE = 8;
+
+
+NET "ROM_ADDR[2]" LOC = P171;
+
+
+NET "ROM_ADDR[2]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[2]" DRIVE = 8;
+
+
+NET "ROM_ADDR[3]" LOC = P165;
+
+
+NET "ROM_ADDR[3]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[3]" DRIVE = 8;
+
+
+NET "ROM_ADDR[4]" LOC = P169;
+
+
+NET "ROM_ADDR[4]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[4]" DRIVE = 8;
+
+
+NET "ROM_ADDR[5]" LOC = P18;
+
+
+NET "ROM_ADDR[5]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[5]" DRIVE = 8;
+
+
+NET "ROM_ADDR[6]" LOC = P175;
+
+
+NET "ROM_ADDR[6]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[6]" DRIVE = 8;
+
+
+NET "ROM_ADDR[7]" LOC = P167;
+
+
+NET "ROM_ADDR[7]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[7]" DRIVE = 8;
+
+
+NET "ROM_ADDR[8]" LOC = P205;
+
+
+NET "ROM_ADDR[8]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[8]" DRIVE = 8;
+
+
+NET "ROM_ADDR[9]" LOC = P204;
+
+
+NET "ROM_ADDR[9]" IOSTANDARD = LVCMOS33;
+NET "ROM_ADDR[9]" DRIVE = 8;
+
+
+NET "ROM_BHE" LOC = P161;
+
+
+NET "ROM_BHE" IOSTANDARD = LVCMOS33;
+NET "ROM_BHE" DRIVE = 8;
+
+
+NET "ROM_BLE" LOC = P156;
+
+
+NET "ROM_BLE" IOSTANDARD = LVCMOS33;
+NET "ROM_BLE" DRIVE = 8;
+
+
+NET "ROM_DATA[0]" LOC = P176;
+
+
+NET "ROM_DATA[0]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[0]" DRIVE = 8;
+
+
+NET "ROM_DATA[10]" LOC = P15;
+
+
+NET "ROM_DATA[10]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[10]" DRIVE = 8;
+
+
+NET "ROM_DATA[11]" LOC = P12;
+
+
+NET "ROM_DATA[11]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[11]" DRIVE = 8;
+
+
+NET "ROM_DATA[12]" LOC = P10;
+
+
+NET "ROM_DATA[12]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[12]" DRIVE = 8;
+
+
+NET "ROM_DATA[13]" LOC = P7;
+
+
+NET "ROM_DATA[13]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[13]" DRIVE = 8;
+
+
+NET "ROM_DATA[14]" LOC = P9;
+
+
+NET "ROM_DATA[14]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[14]" DRIVE = 8;
+
+
+NET "ROM_DATA[15]" LOC = P5;
+
+
+NET "ROM_DATA[15]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[15]" DRIVE = 8;
+
+
+NET "ROM_DATA[1]" LOC = P178;
+
+
+NET "ROM_DATA[1]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[1]" DRIVE = 8;
+
+
+NET "ROM_DATA[2]" LOC = P181;
+
+
+NET "ROM_DATA[2]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[2]" DRIVE = 8;
+
+
+NET "ROM_DATA[3]" LOC = P182;
+
+
+NET "ROM_DATA[3]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[3]" DRIVE = 8;
+
+
+NET "ROM_DATA[4]" LOC = P183;
+
+
+NET "ROM_DATA[4]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[4]" DRIVE = 8;
+
+
+NET "ROM_DATA[5]" LOC = P187;
+
+
+NET "ROM_DATA[5]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[5]" DRIVE = 8;
+
+
+NET "ROM_DATA[6]" LOC = P185;
+
+
+NET "ROM_DATA[6]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[6]" DRIVE = 8;
+
+
+NET "ROM_DATA[7]" LOC = P189;
+
+
+NET "ROM_DATA[7]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[7]" DRIVE = 8;
+
+
+NET "ROM_DATA[8]" LOC = P16;
+
+
+NET "ROM_DATA[8]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[8]" DRIVE = 8;
+
+
+NET "ROM_DATA[9]" LOC = P13;
+
+
+NET "ROM_DATA[9]" IOSTANDARD = LVCMOS33;
+NET "ROM_DATA[9]" DRIVE = 8;
+
+
+NET "ROM_OE" LOC = P162;
+
+
+NET "ROM_OE" IOSTANDARD = LVCMOS33;
+NET "ROM_OE" DRIVE = 8;
+
+
+NET "ROM_WE" LOC = P190;
+
+
+NET "ROM_WE" IOSTANDARD = LVCMOS33;
+NET "ROM_WE" DRIVE = 8;
+NET "SNES_ADDR[0]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[0]" DRIVE = 8;
+NET "SNES_ADDR[10]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[10]" DRIVE = 8;
+NET "SNES_ADDR[11]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[11]" DRIVE = 8;
+NET "SNES_ADDR[12]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[12]" DRIVE = 8;
+NET "SNES_ADDR[13]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[13]" DRIVE = 8;
+NET "SNES_ADDR[14]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[14]" DRIVE = 8;
+NET "SNES_ADDR[15]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[15]" DRIVE = 8;
+NET "SNES_ADDR[16]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[16]" DRIVE = 8;
+NET "SNES_ADDR[17]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[17]" DRIVE = 8;
+NET "SNES_ADDR[18]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[18]" DRIVE = 8;
+NET "SNES_ADDR[19]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[19]" DRIVE = 8;
+NET "SNES_ADDR[1]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[1]" DRIVE = 8;
+NET "SNES_ADDR[20]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[20]" DRIVE = 8;
+NET "SNES_ADDR[21]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[21]" DRIVE = 8;
+NET "SNES_ADDR[22]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[22]" DRIVE = 8;
+NET "SNES_ADDR[23]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[23]" DRIVE = 8;
+NET "SNES_ADDR[2]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[2]" DRIVE = 8;
+NET "SNES_ADDR[3]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[3]" DRIVE = 8;
+NET "SNES_ADDR[4]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[4]" DRIVE = 8;
+NET "SNES_ADDR[5]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[5]" DRIVE = 8;
+NET "SNES_ADDR[6]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[6]" DRIVE = 8;
+NET "SNES_ADDR[7]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[7]" DRIVE = 8;
+NET "SNES_ADDR[8]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[8]" DRIVE = 8;
+NET "SNES_ADDR[9]" IOSTANDARD = LVCMOS33;
+NET "SNES_ADDR[9]" DRIVE = 8;
+
+
+NET "SNES_CPU_CLK" LOC = P95;
+NET "SNES_CS" LOC = P116;
+NET "SNES_DATABUS_DIR" LOC = P111;
+NET "SNES_DATABUS_OE" LOC = P109;
+NET "SNES_DATABUS_DIR" DRIVE = 8;
+NET "SNES_DATABUS_OE" DRIVE = 8;
+
+
+NET "SNES_DATA[0]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[0]" DRIVE = 8;
+NET "SNES_DATA[1]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[1]" DRIVE = 8;
+NET "SNES_DATA[2]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[2]" DRIVE = 8;
+NET "SNES_DATA[3]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[3]" DRIVE = 8;
+NET "SNES_DATA[4]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[4]" DRIVE = 8;
+NET "SNES_DATA[5]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[5]" DRIVE = 8;
+NET "SNES_DATA[6]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[6]" DRIVE = 8;
+NET "SNES_DATA[7]" IOSTANDARD = LVCMOS33;
+NET "SNES_DATA[7]" DRIVE = 8;
+
+
+NET "SNES_IRQ" LOC = P114;
+NET "SNES_READ" LOC = P115;
+NET "SNES_REFRESH" LOC = P155;
+NET "SNES_WRITE" LOC = P94;
+
+NET "SNES_PA[0]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[0]" LOC = P90;
+NET "SNES_PA[1]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[1]" LOC = P93;
+NET "SNES_PA[2]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[2]" LOC = P86;
+NET "SNES_PA[3]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[3]" LOC = P87;
+NET "SNES_PA[4]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[4]" LOC = P81;
+NET "SNES_PA[5]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[5]" LOC = P85;
+NET "SNES_PA[6]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[6]" LOC = P152;
+NET "SNES_PA[7]" IOSTANDARD = LVCMOS33;
+NET "SNES_PA[7]" LOC = P154;
+
+NET "SNES_PARD" IOSTANDARD = LVCMOS33;
+NET "SNES_PARD" LOC = P149;
+NET "SNES_PAWR" IOSTANDARD = LVCMOS33;
+NET "SNES_PAWR" LOC = P150;
+
+NET "SPI_MISO" LOC = P72;
+
+
+NET "SPI_MISO" IOSTANDARD = LVCMOS33;
+NET "SPI_MISO" DRIVE = 8;
+
+
+NET "SPI_MOSI" LOC = P74;
+
+
+NET "SPI_MOSI" IOSTANDARD = LVCMOS33;
+NET "SPI_MOSI" DRIVE = 8;
+
+
+NET "SPI_SS" LOC = P68;
+
+
+NET "SPI_SS" IOSTANDARD = LVCMOS33;
+NET "SPI_SS" DRIVE = 8;
+
+
+NET "DAC_LRCK" LOC = P77;
+
+
+NET "DAC_LRCK" IOSTANDARD = LVCMOS33;
+NET "DAC_LRCK" DRIVE = 8;
+
+
+NET "DAC_MCLK" LOC = P76;
+
+
+NET "DAC_MCLK" IOSTANDARD = LVCMOS33;
+NET "DAC_MCLK" DRIVE = 8;
+
+
+NET "DAC_SDOUT" LOC = P78;
+
+
+NET "DAC_SDOUT" IOSTANDARD = LVCMOS33;
+NET "DAC_SDOUT" DRIVE = 8;
+
+# PlanAhead Generated physical constraints
+
+NET "SD_CLK" LOC = P64;
+NET "SD_CMD" LOC = P67;
+NET "SD_DAT[0]" LOC = P65;
+NET "SD_DAT[1]" LOC = P79;
+NET "SD_DAT[2]" LOC = P62;
+NET "SD_DAT[3]" LOC = P63;
+
+# PlanAhead Generated IO constraints
+
+NET "SD_CLK" IOSTANDARD = LVCMOS33;
+NET "SD_CMD" IOSTANDARD = LVCMOS33;
+NET "SD_DAT[0]" IOSTANDARD = LVCMOS33;
+NET "SD_DAT[1]" IOSTANDARD = LVCMOS33;
+NET "SD_DAT[2]" IOSTANDARD = LVCMOS33;
+NET "SD_DAT[3]" IOSTANDARD = LVCMOS33;
+
+NET "SNES_SYSCLK" LOC = P180;
+NET "SNES_SYSCLK" IOSTANDARD = LVCMOS33;
+
+NET "RAM_DATA[0]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[0]" DRIVE = 8;
+NET "RAM_DATA[0]" LOC = P26;
+NET "RAM_DATA[1]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[1]" DRIVE = 8;
+NET "RAM_DATA[1]" LOC = P22;
+NET "RAM_DATA[2]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[2]" DRIVE = 8;
+NET "RAM_DATA[2]" LOC = P20;
+NET "RAM_DATA[3]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[3]" DRIVE = 8;
+NET "RAM_DATA[3]" LOC = P19;
+NET "RAM_DATA[4]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[4]" DRIVE = 8;
+NET "RAM_DATA[4]" LOC = P21;
+NET "RAM_DATA[5]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[5]" DRIVE = 8;
+NET "RAM_DATA[5]" LOC = P24;
+NET "RAM_DATA[6]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[6]" DRIVE = 8;
+NET "RAM_DATA[6]" LOC = P27;
+NET "RAM_DATA[7]" IOSTANDARD = LVCMOS33;
+NET "RAM_DATA[7]" DRIVE = 8;
+NET "RAM_DATA[7]" LOC = P29;
+
+NET "RAM_OE" IOSTANDARD = LVCMOS33;
+NET "RAM_OE" DRIVE = 8;
+NET "RAM_OE" LOC = P36;
+NET "RAM_WE" IOSTANDARD = LVCMOS33;
+NET "RAM_WE" DRIVE = 8;
+NET "RAM_WE" LOC = P50;
+
+NET "RAM_ADDR[0]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[0]" DRIVE = 8;
+NET "RAM_ADDR[0]" LOC = P28;
+NET "RAM_ADDR[1]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[1]" DRIVE = 8;
+NET "RAM_ADDR[1]" LOC = P31;
+NET "RAM_ADDR[2]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[2]" DRIVE = 8;
+NET "RAM_ADDR[2]" LOC = P33;
+NET "RAM_ADDR[3]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[3]" DRIVE = 8;
+NET "RAM_ADDR[3]" LOC = P35;
+NET "RAM_ADDR[4]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[4]" DRIVE = 8;
+NET "RAM_ADDR[4]" LOC = P37;
+NET "RAM_ADDR[5]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[5]" DRIVE = 8;
+NET "RAM_ADDR[5]" LOC = P40;
+NET "RAM_ADDR[6]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[6]" DRIVE = 8;
+NET "RAM_ADDR[6]" LOC = P43;
+NET "RAM_ADDR[7]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[7]" DRIVE = 8;
+NET "RAM_ADDR[7]" LOC = P45;
+NET "RAM_ADDR[8]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[8]" DRIVE = 8;
+NET "RAM_ADDR[8]" LOC = P44;
+NET "RAM_ADDR[9]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[9]" DRIVE = 8;
+NET "RAM_ADDR[9]" LOC = P42;
+NET "RAM_ADDR[10]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[10]" DRIVE = 8;
+NET "RAM_ADDR[10]" LOC = P34;
+NET "RAM_ADDR[11]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[11]" DRIVE = 8;
+NET "RAM_ADDR[11]" LOC = P39;
+NET "RAM_ADDR[12]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[12]" DRIVE = 8;
+NET "RAM_ADDR[12]" LOC = P48;
+NET "RAM_ADDR[13]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[13]" DRIVE = 8;
+NET "RAM_ADDR[13]" LOC = P46;
+NET "RAM_ADDR[14]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[14]" DRIVE = 8;
+NET "RAM_ADDR[14]" LOC = P51;
+NET "RAM_ADDR[15]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[15]" DRIVE = 8;
+NET "RAM_ADDR[15]" LOC = P58;
+NET "RAM_ADDR[16]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[16]" DRIVE = 8;
+NET "RAM_ADDR[16]" LOC = P57;
+NET "RAM_ADDR[17]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[17]" DRIVE = 8;
+NET "RAM_ADDR[17]" LOC = P61;
+NET "RAM_ADDR[18]" IOSTANDARD = LVCMOS33;
+NET "RAM_ADDR[18]" DRIVE = 8;
+NET "RAM_ADDR[18]" LOC = P52;
diff --git a/verilog/sd2snes_test/main.v b/verilog/sd2snes_test/main.v
new file mode 100644
index 0000000..e1adc44
--- /dev/null
+++ b/verilog/sd2snes_test/main.v
@@ -0,0 +1,596 @@
+`timescale 1 ns / 1 ns
+//////////////////////////////////////////////////////////////////////////////////
+// Company: Rehkopf
+// Engineer: Rehkopf
+//
+// Create Date: 01:13:46 05/09/2009
+// Design Name:
+// Module Name: main
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description: Master Control FSM
+//
+// Dependencies: address
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module main(
+ /* input clock */
+ input CLKIN,
+
+ /* SNES signals */
+ input [23:0] SNES_ADDR,
+ input SNES_READ,
+ input SNES_WRITE,
+ input SNES_CS,
+ inout [7:0] SNES_DATA,
+ input SNES_CPU_CLK,
+ input SNES_REFRESH,
+ output SNES_IRQ,
+ output SNES_DATABUS_OE,
+ output SNES_DATABUS_DIR,
+ input SNES_SYSCLK,
+
+ input [7:0] SNES_PA,
+ input SNES_PARD,
+ input SNES_PAWR,
+
+ /* SRAM signals */
+ /* Bus 1: PSRAM, 128Mbit, 16bit, 70ns */
+ inout [15:0] ROM_DATA,
+ output [22:0] ROM_ADDR,
+ output ROM_CE,
+ output ROM_OE,
+ output ROM_WE,
+ output ROM_BHE,
+ output ROM_BLE,
+
+ /* Bus 2: SRAM, 4Mbit, 8bit, 45ns */
+ inout [7:0] RAM_DATA,
+ output [18:0] RAM_ADDR,
+ output RAM_OE,
+ output RAM_WE,
+
+ /* MCU signals */
+ input SPI_MOSI,
+ inout SPI_MISO,
+ input SPI_SS,
+ inout SPI_SCK,
+ input MCU_OVR,
+ output MCU_RDY,
+
+ output DAC_MCLK,
+ output DAC_LRCK,
+ output DAC_SDOUT,
+
+ /* SD signals */
+ input [3:0] SD_DAT,
+ inout SD_CMD,
+ inout SD_CLK,
+
+ /* debug */
+ output p113_out
+);
+
+wire [31:0] snes_sysclk_freq;
+wire [31:0] snes_read_freq;
+wire [31:0] snes_write_freq;
+wire [31:0] snes_pard_freq;
+wire [31:0] snes_pawr_freq;
+wire [31:0] snes_refresh_freq;
+wire [31:0] snes_cpuclk_freq;
+wire [31:0] snes_romsel_freq;
+
+clk_test snes_clk_test (
+ .clk(CLK2),
+ .sysclk(SNES_SYSCLK),
+ .read(SNES_READ),
+ .write(SNES_WRITE),
+ .pard(SNES_PARD),
+ .pawr(SNES_PAWR),
+ .refresh(SNES_REFRESH),
+ .cpuclk(SNES_CPU_CLK),
+ .romsel(SNES_CS),
+ .snes_sysclk_freq(snes_sysclk_freq),
+ .snes_read_freq(snes_read_freq),
+ .snes_write_freq(snes_write_freq),
+ .snes_pard_freq(snes_pard_freq),
+ .snes_pawr_freq(snes_pawr_freq),
+ .snes_refresh_freq(snes_refresh_freq),
+ .snes_cpuclk_freq(snes_cpuclk_freq),
+ .snes_romsel_freq(snes_romsel_freq)
+);
+
+wire [7:0] spi_cmd_data;
+wire [7:0] spi_param_data;
+wire [7:0] spi_input_data;
+wire [31:0] spi_byte_cnt;
+wire [2:0] spi_bit_cnt;
+wire [23:0] MCU_ADDR;
+wire [2: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 [23:0] ram0_addr;
+wire [18:0] ram1_addr;
+wire [7:0] PA_addr;
+wire [12:0] bram_addr;
+wire ROM_ADDR0;
+
+sd_dma snes_sd_dma(
+ .CLK(CLK2),
+ .SD_DAT(SD_DAT),
+ .SD_CLK(SD_CLK),
+ .SD_DMA_EN(SD_DMA_EN),
+ .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_PARTIAL(SD_DMA_PARTIAL),
+ .SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START),
+ .SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END)
+);
+
+wire SD_DMA_TO_ROM = (SD_DMA_STATUS && (SD_DMA_TGT == 2'b00));
+
+dac snes_dac(
+ .clkin(CLK2),
+ .sysclk(SNES_SYSCLK),
+ .mclk(DAC_MCLK),
+ .lrck(DAC_LRCK),
+ .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),
+ .play(dac_play),
+ .reset(dac_reset)
+);
+
+spi snes_spi(
+ .clk(CLK2),
+ .MOSI(SPI_MOSI),
+ .MISO(SPI_MISO),
+ .SSEL(SPI_SS),
+ .SCK(SPI_SCK),
+ .cmd_ready(spi_cmd_ready),
+ .param_ready(spi_param_ready),
+ .cmd_data(spi_cmd_data),
+ .param_data(spi_param_data),
+ .endmessage(spi_endmessage),
+ .startmessage(spi_startmessage),
+ .input_data(spi_input_data),
+ .byte_cnt(spi_byte_cnt),
+ .bit_cnt(spi_bit_cnt)
+);
+
+reg [7:0] MCU_DINr;
+wire [7:0] MCU_DOUT;
+
+wire [7:0] mcu_bram_data_in;
+wire [7:0] mcu_bram_data_out;
+wire [12:0] mcu_bram_addr;
+
+mcu_cmd snes_mcu_cmd(
+ .clk(CLK2),
+ .cmd_ready(spi_cmd_ready),
+ .param_ready(spi_param_ready),
+ .cmd_data(spi_cmd_data),
+ .param_data(spi_param_data),
+ .mcu_mapper(MAPPER),
+ .mcu_write(MCU_WRITE),
+ .mcu_data_in(MCU_DINr),
+ .mcu_data_out(MCU_DOUT),
+ .spi_byte_cnt(spi_byte_cnt),
+ .spi_bit_cnt(spi_bit_cnt),
+ .spi_data_out(spi_input_data),
+ .addr_out(MCU_ADDR),
+ .saveram_mask_out(SAVERAM_MASK),
+ .rom_mask_out(ROM_MASK),
+ .SD_DMA_EN(SD_DMA_EN),
+ .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_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),
+ .featurebits_out(featurebits),
+ .mcu_rrq(MCU_RRQ),
+ .mcu_wrq(MCU_WRQ),
+ .mcu_rq_rdy(MCU_RDY),
+ .ramsel_out(MCU_RAMSEL),
+ .snes_sysclk_freq(snes_sysclk_freq),
+ .snes_read_freq(snes_read_freq),
+ .snes_write_freq(snes_write_freq),
+ .snes_pard_freq(snes_pard_freq),
+ .snes_pawr_freq(snes_pawr_freq),
+ .snes_refresh_freq(snes_refresh_freq),
+ .snes_cpuclk_freq(snes_cpuclk_freq),
+ .snes_romsel_freq(snes_romsel_freq),
+ .mcu_bram_addr(mcu_bram_addr),
+ .mcu_bram_data_in(mcu_bram_data_in),
+ .mcu_bram_data_out(mcu_bram_data_out),
+ .mcu_bram_we(mcu_bram_we)
+);
+
+wire [7:0] DCM_STATUS;
+// dcm1: dfs 4x
+my_dcm snes_dcm(
+ .CLKIN(CLKIN),
+ .CLKFX(CLK2),
+ .LOCKED(DCM_LOCKED),
+ .RST(DCM_RST),
+ .STATUS(DCM_STATUS)
+);
+
+assign DCM_RST=0;
+
+reg [5:0] SNES_READr;
+reg [5:0] SNES_WRITEr;
+reg [5:0] SNES_CPU_CLKr;
+
+wire SNES_RD_start = (SNES_READr == 6'b111110);
+wire SNES_WR_start = (SNES_WRITEr == 6'b111110);
+wire SNES_WR_rising = (SNES_WRITEr == 6'b000001);
+wire SNES_cycle_start = (SNES_CPU_CLKr[5:0] == 6'b000001);
+wire SNES_cycle_end = (SNES_CPU_CLKr[5:0] == 6'b111110);
+
+always @(posedge CLK2) begin
+ SNES_READr <= {SNES_READr[4:0], SNES_READ};
+ SNES_WRITEr <= {SNES_WRITEr[4:0], SNES_WRITE};
+ SNES_CPU_CLKr <= {SNES_CPU_CLKr[4:0], SNES_CPU_CLK};
+end
+
+reg [7:0] ram0_bank;
+initial ram0_bank = 8'h00;
+reg ram0_linear;
+initial ram0_linear = 1'b0;
+
+address snes_addr(
+ .CLK(CLK2),
+ .SNES_ADDR(SNES_ADDR), // requested address from SNES
+ .ram0_addr(ram0_addr), // Address to request from SRAM (active low)
+ .ram1_addr(ram1_addr),
+ .PA_addr(PA_addr),
+ .bram_addr(bram_addr),
+ .ram0_enable(ram0_enable),
+ .ram1_enable(ram1_enable),
+ .PA_enable(PA_enable),
+ .bram_enable(bram_enable),
+ .ram0_bank(ram0_bank),
+ .ram0_linear(ram0_linear),
+ .irq_enable(irq_enable),
+ .bank_enable(bank_enable),
+ .linear_enable(linear_enable)
+);
+
+always @(posedge CLK2) begin
+ if(SNES_WR_rising && bank_enable) ram0_bank <= SNES_DATA;
+end
+
+always @(posedge CLK2) begin
+ if(SNES_WR_rising && linear_enable) ram0_linear <= SNES_DATA[0];
+end
+
+reg [7:0] irq_count_r;
+initial irq_count_r = 8'b0;
+reg SNES_IRQr;
+initial SNES_IRQr = 0;
+
+always @(posedge CLK2) begin
+ if(SNES_WR_rising & irq_enable) SNES_IRQr <= 1'b1;
+ else if(irq_count_r == 8'h00) SNES_IRQr <= 1'b0;
+end
+
+always @(posedge CLK2) begin
+ if(SNES_WR_rising & irq_enable) irq_count_r <= 8'h01;
+ else irq_count_r <= irq_count_r + 1;
+end
+
+
+wire [7:0] bram_data_out;
+bram test_bram (
+ .clka(CLK2), // input clka
+ .wea(~SNES_WRITE & bram_enable), // input [0 : 0] wea
+ .addra(bram_addr), // input [12 : 0] addra
+ .dina(SNES_DATA), // input [7 : 0] dina
+ .douta(bram_data_out), // output [7 : 0] douta
+ .clkb(CLK2), // input clkb
+ .web(mcu_bram_we), // input [0 : 0] web
+ .addrb(mcu_bram_addr), // input [12 : 0] addrb
+ .dinb(mcu_bram_data_out), // input [7 : 0] dinb
+ .doutb(mcu_bram_data_in) // output [7 : 0] doutb
+);
+reg [1:0] SNES_PAWR_start_r;
+always @(posedge CLK2) SNES_PAWR_start_r <= {SNES_PAWR_start_r[0], SNES_PAWR};
+wire SNES_PAWR_start = (SNES_PAWR_start_r == 2'b01);
+wire [7:0] PA_data_out;
+PA test_PA (
+ .clka(CLK2), // input clka
+ .wea(SNES_PAWR_start), // input [0 : 0] wea
+ .addra(SNES_PA), // input [7 : 0] addra
+ .dina(SNES_DATA), // input [7 : 0] dina
+ .clkb(CLK2), // input clkb
+ .addrb(PA_addr), // input [7 : 0] addrb
+ .doutb(PA_data_out) // output [7 : 0] doutb
+);
+
+parameter MODE_SNES = 1'b0;
+parameter MODE_MCU = 1'b1;
+
+parameter ST_IDLE = 18'b000000000000000001;
+parameter ST_SNES_RD_ADDR = 18'b000000000000000010;
+parameter ST_SNES_RD_WAIT = 18'b000000000000000100;
+parameter ST_SNES_RD_END = 18'b000000000000001000;
+parameter ST_SNES_WR_ADDR = 18'b000000000000010000;
+parameter ST_SNES_WR_WAIT1= 18'b000000000000100000;
+parameter ST_SNES_WR_DATA = 18'b000000000001000000;
+parameter ST_SNES_WR_WAIT2= 18'b000000000010000000;
+parameter ST_SNES_WR_END = 18'b000000000100000000;
+parameter ST_MCU_RD_ADDR = 18'b000000001000000000;
+parameter ST_MCU_RD_WAIT = 18'b000000010000000000;
+parameter ST_MCU_RD_WAIT2 = 18'b000000100000000000;
+parameter ST_MCU_RD_END = 18'b000001000000000000;
+parameter ST_MCU_WR_ADDR = 18'b000010000000000000;
+parameter ST_MCU_WR_WAIT = 18'b000100000000000000;
+parameter ST_MCU_WR_WAIT2 = 18'b001000000000000000;
+parameter ST_MCU_WR_END = 18'b010000000000000000;
+
+parameter ROM_RD_WAIT = 4'h4;
+parameter ROM_RD_WAIT_MCU = 4'h6;
+parameter ROM_WR_WAIT1 = 4'h2;
+parameter ROM_WR_WAIT2 = 4'h3;
+parameter ROM_WR_WAIT_MCU = 4'h6;
+
+reg [17:0] STATE;
+initial STATE = ST_IDLE;
+
+reg [7:0] SNES_DINr;
+reg [7:0] ROM_DOUTr;
+reg [7:0] RAM_DOUTr;
+
+assign SNES_DATA = (!SNES_READ) ? (ram0_enable ? SNES_DINr
+ :ram1_enable ? SNES_DINr
+ :bram_enable ? bram_data_out
+ :PA_enable ? PA_data_out
+ :SNES_DINr /*(ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8])*/) : 8'bZ;
+
+reg [3:0] ST_MEM_DELAYr;
+reg MCU_RD_PENDr;
+reg MCU_WR_PENDr;
+reg [23:0] ROM_ADDRr;
+reg [18:0] RAM_ADDRr;
+reg NEED_SNES_ADDRr;
+always @(posedge CLK2) begin
+ if(SNES_cycle_end) NEED_SNES_ADDRr <= 1'b1;
+ else if(STATE & (ST_SNES_RD_END | ST_SNES_WR_END)) NEED_SNES_ADDRr <= 1'b0;
+end
+
+wire ASSERT_SNES_ADDR = SNES_CPU_CLK & NEED_SNES_ADDRr;
+
+assign ROM_ADDR = (SD_DMA_TO_ROM) ? MCU_ADDR[23:1] : (ASSERT_SNES_ADDR) ? ram0_addr[23:1] : ROM_ADDRr[23:1];
+assign ROM_ADDR0 = (SD_DMA_TO_ROM) ? MCU_ADDR[0] : (ASSERT_SNES_ADDR) ? ram0_addr[0] : ROM_ADDRr[0];
+
+assign RAM_ADDR = ASSERT_SNES_ADDR ? ram1_addr : RAM_ADDRr;
+
+reg ROM_WEr;
+initial ROM_WEr = 1'b1;
+
+reg RAM_WEr;
+initial RAM_WEr = 1'b1;
+
+reg RQ_MCU_RDYr;
+initial RQ_MCU_RDYr = 1'b1;
+assign MCU_RDY = RQ_MCU_RDYr;
+
+always @(posedge CLK2) begin
+ if(MCU_RRQ) begin
+ MCU_RD_PENDr <= 1'b1;
+ RQ_MCU_RDYr <= 1'b0;
+ end else if(MCU_WRQ) begin
+ MCU_WR_PENDr <= 1'b1;
+ RQ_MCU_RDYr <= 1'b0;
+ end else if(STATE & (ST_MCU_RD_END | ST_MCU_WR_END)) begin
+ MCU_RD_PENDr <= 1'b0;
+ MCU_WR_PENDr <= 1'b0;
+ RQ_MCU_RDYr <= 1'b1;
+ end
+end
+
+reg snes_wr_cycle;
+wire ram_enable = ram0_enable | ram1_enable;
+always @(posedge CLK2) begin
+ if(ram_enable & SNES_cycle_start & ~SNES_WR_start) begin
+ STATE <= ST_SNES_RD_ADDR;
+ end else if(ram_enable & SNES_WR_start) begin
+ snes_wr_cycle <= 1'b1;
+ STATE <= ST_SNES_WR_ADDR;
+ end else begin
+ case(STATE)
+ ST_IDLE: begin
+ if(ram0_enable) ROM_ADDRr <= ram0_addr;
+ if(ram1_enable) RAM_ADDRr <= ram1_addr;
+ if(MCU_RD_PENDr) STATE <= ST_MCU_RD_ADDR;
+ else if(MCU_WR_PENDr) STATE <= ST_MCU_WR_ADDR;
+ else STATE <= ST_IDLE;
+ end
+ ST_SNES_RD_ADDR: begin
+ STATE <= ST_SNES_RD_WAIT;
+ ST_MEM_DELAYr <= ROM_RD_WAIT;
+ end
+ ST_SNES_RD_WAIT: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_RD_END;
+ else STATE <= ST_SNES_RD_WAIT;
+ if(ram0_enable) begin
+ if(ROM_ADDR0) SNES_DINr <= ROM_DATA[7:0];
+ else SNES_DINr <= ROM_DATA[15:8];
+ end else if(ram1_enable) begin
+ SNES_DINr <= RAM_DATA[7:0];
+ end
+ end
+ ST_SNES_RD_END: begin
+ STATE <= ST_IDLE;
+ if(ram0_enable) begin
+ if(ROM_ADDR0) SNES_DINr <= ROM_DATA[7:0];
+ else SNES_DINr <= ROM_DATA[15:8];
+ end else if(ram1_enable) begin
+ SNES_DINr <= RAM_DATA[7:0];
+ end
+ end
+ ST_SNES_WR_ADDR: begin
+ if(ram0_enable) ROM_WEr <= 1'b0;
+ if(ram1_enable) RAM_WEr <= 1'b0;
+ STATE <= ST_SNES_WR_WAIT1;
+ ST_MEM_DELAYr <= ROM_WR_WAIT1;
+ end
+ ST_SNES_WR_WAIT1: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_WR_DATA;
+ else STATE <= ST_SNES_WR_WAIT1;
+ end
+ ST_SNES_WR_DATA: begin
+ if(ram0_enable) ROM_DOUTr <= SNES_DATA;
+ if(ram1_enable) RAM_DOUTr <= SNES_DATA;
+ ST_MEM_DELAYr <= ROM_WR_WAIT2;
+ STATE <= ST_SNES_WR_WAIT2;
+ end
+ ST_SNES_WR_WAIT2: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) STATE <= ST_SNES_WR_END;
+ else STATE <= ST_SNES_WR_WAIT2;
+ end
+ ST_SNES_WR_END: begin
+ STATE <= ST_IDLE;
+ ROM_WEr <= 1'b1;
+ RAM_WEr <= 1'b1;
+ snes_wr_cycle <= 1'b0;
+ end
+ ST_MCU_RD_ADDR: begin
+ if(MCU_RAMSEL == 1'b0) ROM_ADDRr <= MCU_ADDR;
+ else RAM_ADDRr <= MCU_ADDR;
+ STATE <= ST_MCU_RD_WAIT;
+ ST_MEM_DELAYr <= ROM_RD_WAIT_MCU;
+ end
+ ST_MCU_RD_WAIT: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) begin
+ STATE <= ST_MCU_RD_WAIT2;
+ ST_MEM_DELAYr <= 4'h2;
+ end
+ else STATE <= ST_MCU_RD_WAIT;
+ if(MCU_RAMSEL == 1'b0) begin
+ if(ROM_ADDR0) MCU_DINr <= ROM_DATA[7:0];
+ else MCU_DINr <= ROM_DATA[15:8];
+ end else MCU_DINr <= RAM_DATA;
+ end
+ ST_MCU_RD_WAIT2: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) begin
+ STATE <= ST_MCU_RD_END;
+ end else STATE <= ST_MCU_RD_WAIT2;
+ end
+ ST_MCU_RD_END: begin
+ STATE <= ST_IDLE;
+ end
+ ST_MCU_WR_ADDR: begin
+ if(MCU_RAMSEL == 1'b0) ROM_ADDRr <= MCU_ADDR;
+ else RAM_ADDRr <= MCU_ADDR;
+ STATE <= ST_MCU_WR_WAIT;
+ ST_MEM_DELAYr <= ROM_WR_WAIT_MCU;
+ if(MCU_RAMSEL == 1'b0) ROM_DOUTr <= MCU_DOUT;
+ else RAM_DOUTr <= MCU_DOUT;
+ if(MCU_RAMSEL == 1'b0)
+ ROM_WEr <= 1'b0;
+ else if(MCU_RAMSEL == 1'b1)
+ RAM_WEr <= 1'b0;
+ end
+ ST_MCU_WR_WAIT: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) begin
+ ROM_WEr <= 1'b1;
+ RAM_WEr <= 1'b1;
+ STATE <= ST_MCU_WR_WAIT2;
+ ST_MEM_DELAYr <= 4'h2;
+ end
+ else begin
+ STATE <= ST_MCU_WR_WAIT;
+ end
+ end
+ ST_MCU_WR_WAIT2: begin
+ ST_MEM_DELAYr <= ST_MEM_DELAYr - 4'h1;
+ if(ST_MEM_DELAYr == 4'h0) begin
+ STATE <= ST_MCU_WR_END;
+ end else STATE <= ST_MCU_WR_WAIT2;
+ end
+ ST_MCU_WR_END: begin
+ STATE <= ST_IDLE;
+ end
+ endcase
+ end
+end
+
+assign ROM_DATA[7:0] = ROM_ADDR0
+ ?(SD_DMA_TO_ROM ? (!MCU_WRITE ? MCU_DOUT : 8'bZ)
+ : (!ROM_WE ? ROM_DOUTr : 8'bZ)
+ )
+ :8'bZ;
+
+assign ROM_DATA[15:8] = ROM_ADDR0 ? 8'bZ
+ :(SD_DMA_TO_ROM ? (!MCU_WRITE ? MCU_DOUT : 8'bZ)
+ : (!ROM_WE ? ROM_DOUTr : 8'bZ)
+ );
+
+assign RAM_DATA = !RAM_WE ? RAM_DOUTr : 8'bZ;
+
+assign ROM_WE = SD_DMA_TO_ROM
+ ?MCU_WRITE
+ :ROM_WEr | (ASSERT_SNES_ADDR & ~(snes_wr_cycle & ram0_enable));
+
+assign RAM_WE = RAM_WEr | (ASSERT_SNES_ADDR & ~(snes_wr_cycle & ram1_enable));
+
+assign RAM_OE = 1'b0;
+
+// OE always active. Overridden by WE when needed.
+assign ROM_OE = 1'b0;
+
+assign ROM_CE = 1'b0;
+
+assign ROM_BHE = !ROM_WE ? ROM_ADDR0 : 1'b0;
+assign ROM_BLE = !ROM_WE ? !ROM_ADDR0 : 1'b0;
+
+assign SNES_DATABUS_OE = PA_enable ? 1'b0
+ : bram_enable ? 1'b0
+ : (~SNES_PAWR & SNES_READ) ? 1'b0
+ : SNES_CS ? SNES_WRITE
+ :((SNES_CS)
+ |(!ram0_enable & !ram1_enable)
+ |(SNES_READ & SNES_WRITE)
+ );
+
+assign SNES_DATABUS_DIR = ~SNES_READ ? 1'b1 : 1'b0;
+
+assign IRQ_DIR = 1'b0;
+assign SNES_IRQ = SNES_IRQr;
+
+assign p113_out = 1'b0;
+
+endmodule
diff --git a/verilog/sd2snes_test/mcu_cmd.v b/verilog/sd2snes_test/mcu_cmd.v
new file mode 100644
index 0000000..c5e2bb7
--- /dev/null
+++ b/verilog/sd2snes_test/mcu_cmd.v
@@ -0,0 +1,618 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 21:57:50 08/25/2009
+// Design Name:
+// Module Name: mcu_cmd
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module mcu_cmd(
+ input clk,
+ input cmd_ready,
+ input param_ready,
+ input [7:0] cmd_data,
+ input [7:0] param_data,
+ output [2:0] mcu_mapper,
+ output mcu_rrq,
+ output mcu_write,
+ output mcu_wrq,
+ input mcu_rq_rdy,
+ output [7:0] mcu_data_out,
+ input [7:0] mcu_data_in,
+ output [7:0] spi_data_out,
+ input [31:0] spi_byte_cnt,
+ input [2:0] spi_bit_cnt,
+ output [23:0] addr_out,
+ output [23:0] saveram_mask_out,
+ output [23:0] rom_mask_out,
+ output reg ramsel_out,
+
+ // 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,
+ output [1:0] SD_DMA_TGT,
+ output SD_DMA_PARTIAL,
+ output [10:0] SD_DMA_PARTIAL_START,
+ output [10:0] SD_DMA_PARTIAL_END,
+
+ // DAC
+ output [10:0] dac_addr_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,
+ output [13:0] msu_ptr_out,
+ output msu_reset_out,
+
+ // BS-X
+ output [7:0] bsx_regs_reset_out,
+ output [7:0] bsx_regs_set_out,
+ output bsx_regs_reset_we,
+
+ // generic RTC
+ output [55:0] rtc_data_out,
+ output rtc_pgm_we,
+
+ // S-RTC
+ output srtc_reset,
+
+ // uPD77C25
+ output reg [23:0] dspx_pgm_data_out,
+ output reg [10:0] dspx_pgm_addr_out,
+ output reg dspx_pgm_we_out,
+
+ output reg [15:0] dspx_dat_data_out,
+ output reg [10:0] dspx_dat_addr_out,
+ output reg dspx_dat_we_out,
+
+ output reg dspx_reset_out,
+
+ // feature enable
+ output reg [3:0] featurebits_out,
+
+ // SNES control signal/clock freqs
+
+ input [31:0] snes_cpuclk_freq,
+ input [31:0] snes_sysclk_freq,
+ input [31:0] snes_read_freq,
+ input [31:0] snes_write_freq,
+ input [31:0] snes_pard_freq,
+ input [31:0] snes_pawr_freq,
+ input [31:0] snes_refresh_freq,
+ input [31:0] snes_romsel_freq,
+
+ output reg [12:0] mcu_bram_addr,
+ input [7:0] mcu_bram_data_in,
+ output reg [7:0] mcu_bram_data_out,
+ output reg mcu_bram_we
+
+);
+
+initial begin
+ dspx_pgm_addr_out = 11'b00000000000;
+ dspx_dat_addr_out = 10'b0000000000;
+ dspx_reset_out = 1'b1;
+ ramsel_out = 1'b0;
+end
+
+reg [2:0] MAPPER_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 [13:0] MSU_PTR_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 MSU_RESET_OUT_BUF;
+
+reg [7:0] bsx_regs_set_out_buf;
+reg [7:0] bsx_regs_reset_out_buf;
+reg bsx_regs_reset_we_buf;
+
+reg [55:0] rtc_data_out_buf;
+reg rtc_pgm_we_buf;
+
+reg srtc_reset_buf;
+
+reg [31:0] SNES_SYSCLK_FREQ_BUF;
+
+reg [7:0] MCU_DATA_OUT_BUF;
+reg [7:0] MCU_DATA_IN_BUF;
+reg [1:0] mcu_nextaddr_buf;
+
+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 [10:0] SD_DMA_PARTIAL_STARTr;
+reg [10:0] SD_DMA_PARTIAL_ENDr;
+assign SD_DMA_PARTIAL_START = SD_DMA_PARTIAL_STARTr;
+assign SD_DMA_PARTIAL_END = SD_DMA_PARTIAL_ENDr;
+
+reg [23:0] SAVERAM_MASK;
+reg [23:0] ROM_MASK;
+
+assign spi_data_out = MCU_DATA_IN_BUF;
+
+initial begin
+ ADDR_OUT_BUF = 0;
+ DAC_ADDR_OUT_BUF = 0;
+ MSU_ADDR_OUT_BUF = 0;
+ SD_DMA_ENr = 0;
+ MAPPER_BUF = 1;
+end
+
+// command interpretation
+always @(posedge clk) begin
+ if (cmd_ready) begin
+ case (cmd_data[7:4])
+ 4'h3: // select mapper
+ MAPPER_BUF <= cmd_data[2:0];
+ 4'h4: begin// SD DMA
+ SD_DMA_ENr <= 1;
+ SD_DMA_TGTr <= cmd_data[1:0];
+ SD_DMA_PARTIALr <= cmd_data[2];
+ end
+ 4'h8: SD_DMA_TGTr <= 2'b00;
+ 4'h9: SD_DMA_TGTr <= cmd_data[1:0]; // not implemented
+ endcase
+ end else if (param_ready) begin
+ casex (cmd_data[7:0])
+ 8'h1x:
+ case (spi_byte_cnt)
+ 32'h2:
+ ROM_MASK[23:16] <= param_data;
+ 32'h3:
+ ROM_MASK[15:8] <= param_data;
+ 32'h4:
+ ROM_MASK[7:0] <= param_data;
+ endcase
+ 8'h2x:
+ case (spi_byte_cnt)
+ 32'h2:
+ SAVERAM_MASK[23:16] <= param_data;
+ 32'h3:
+ SAVERAM_MASK[15:8] <= param_data;
+ 32'h4:
+ SAVERAM_MASK[7:0] <= param_data;
+ endcase
+ 8'h4x:
+ SD_DMA_ENr <= 1'b0;
+ 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
+ 8'he4: // reset MSU read buffer pointer
+ case (spi_byte_cnt)
+ 32'h2: begin
+ MSU_PTR_OUT_BUF[13:8] <= param_data[5:0];
+ MSU_PTR_OUT_BUF[7:0] <= 8'h0;
+ end
+ 32'h3: begin
+ MSU_PTR_OUT_BUF[7:0] <= param_data;
+ MSU_RESET_OUT_BUF <= 1'b1;
+ end
+ 32'h4:
+ MSU_RESET_OUT_BUF <= 1'b0;
+ endcase
+ 8'he5:
+ case (spi_byte_cnt)
+ 32'h2:
+ rtc_data_out_buf[55:48] <= param_data;
+ 32'h3:
+ rtc_data_out_buf[47:40] <= param_data;
+ 32'h4:
+ rtc_data_out_buf[39:32] <= param_data;
+ 32'h5:
+ rtc_data_out_buf[31:24] <= param_data;
+ 32'h6:
+ rtc_data_out_buf[23:16] <= param_data;
+ 32'h7:
+ rtc_data_out_buf[15:8] <= param_data;
+ 32'h8: begin
+ rtc_data_out_buf[7:0] <= param_data;
+ rtc_pgm_we_buf <= 1'b1;
+ end
+ 32'h9:
+ rtc_pgm_we_buf <= 1'b0;
+ endcase
+ 8'he6:
+ case (spi_byte_cnt)
+ 32'h2: begin
+ bsx_regs_set_out_buf <= param_data[7:0];
+ end
+ 32'h3: begin
+ bsx_regs_reset_out_buf <= param_data[7:0];
+ bsx_regs_reset_we_buf <= 1'b1;
+ end
+ 32'h4:
+ bsx_regs_reset_we_buf <= 1'b0;
+ endcase
+ 8'he7:
+ case (spi_byte_cnt)
+ 32'h2: begin
+ srtc_reset_buf <= 1'b1;
+ end
+ 32'h3: begin
+ srtc_reset_buf <= 1'b0;
+ end
+ endcase
+ 8'he8: begin // set BRAM address
+ case (spi_byte_cnt)
+ 32'h2: mcu_bram_addr[12:8] <= param_data[4:0];
+ 32'h3: mcu_bram_addr[7:0] <= param_data[7:0];
+ endcase
+ end
+ 8'he9: begin // write BRAM
+ case (spi_byte_cnt)
+ 32'h2: begin
+ mcu_bram_data_out <= param_data;
+ mcu_bram_we <= 1'b1;
+ end
+ 32'h3: mcu_bram_we <= 1'b0;
+ 32'h4: mcu_bram_addr <= mcu_bram_addr + 1;
+ endcase
+ end
+ 8'hee:
+ ramsel_out <= param_data[0];
+ 8'hf5:
+ if (spi_byte_cnt == 32'h3) mcu_bram_addr <= mcu_bram_addr + 1;
+ endcase
+ end
+end
+
+always @(posedge clk) begin
+ if(param_ready && cmd_data[7:4] == 4'h0) begin
+ 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
+ end else if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4)
+ && (cmd_data[3])
+ && (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
+always @(posedge clk) begin
+ if (cmd_data[7:4] == 4'h8 && mcu_nextaddr_buf == 2'b01)
+ MCU_DATA_IN_BUF <= mcu_data_in;
+ else if (spi_bit_cnt == 3'h7) begin
+ if (cmd_data[7:0] == 8'hF0)
+ MCU_DATA_IN_BUF <= 8'hA5;
+ else if (cmd_data[7:0] == 8'hF1)
+ case (spi_byte_cnt[0])
+ 1'b1: // buffer status (1st byte)
+ MCU_DATA_IN_BUF <= {SD_DMA_STATUSr, DAC_STATUSr, MSU_STATUSr[6], 5'b0};
+ 1'b0: // control status (2nd byte)
+ 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)
+ 32'h1:
+ MCU_DATA_IN_BUF <= msu_trackrq[15:8];
+ 32'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'hF5)
+ MCU_DATA_IN_BUF <= mcu_bram_data_in;
+ else if (cmd_data[7:0] == 8'hF7)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_romsel_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hF8)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_cpuclk_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hF9)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_read_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hFA)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_write_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hFB)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_pard_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hFC)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_pawr_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hFD)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_refresh_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hFE)
+ case (spi_byte_cnt)
+ 32'h1:
+ SNES_SYSCLK_FREQ_BUF <= snes_sysclk_freq;
+ 32'h2:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[31:24];
+ 32'h3:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[23:16];
+ 32'h4:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[15:8];
+ 32'h5:
+ MCU_DATA_IN_BUF <= SNES_SYSCLK_FREQ_BUF[7:0];
+ endcase
+ else if (cmd_data[7:0] == 8'hFF)
+ MCU_DATA_IN_BUF <= param_data;
+ end
+end
+
+// nextaddr pulse generation
+always @(posedge clk) begin
+ mcu_nextaddr_buf <= {mcu_nextaddr_buf[0], mcu_rq_rdy};
+end
+
+parameter ST_RQ = 2'b01;
+parameter ST_IDLE = 2'b10;
+
+reg [1:0] rrq_state;
+initial rrq_state = ST_IDLE;
+reg mcu_rrq_r;
+
+reg [1:0] wrq_state;
+initial wrq_state = ST_IDLE;
+reg mcu_wrq_r;
+
+always @(posedge clk) begin
+ case(rrq_state)
+ ST_IDLE: begin
+ if((param_ready | cmd_ready) && cmd_data[7:4] == 4'h8) begin
+ mcu_rrq_r <= 1'b1;
+ rrq_state <= ST_RQ;
+ end else
+ rrq_state <= ST_IDLE;
+ end
+ ST_RQ: begin
+ mcu_rrq_r <= 1'b0;
+ rrq_state <= ST_IDLE;
+ end
+ endcase
+end
+
+always @(posedge clk) begin
+ case(wrq_state)
+ ST_IDLE: begin
+ if(param_ready && cmd_data[7:4] == 4'h9) begin
+ mcu_wrq_r <= 1'b1;
+ wrq_state <= ST_RQ;
+ end else
+ wrq_state <= ST_IDLE;
+ end
+ ST_RQ: begin
+ mcu_wrq_r <= 1'b0;
+ wrq_state <= ST_IDLE;
+ end
+ endcase
+end
+
+// trigger for nextaddr
+assign mcu_nextaddr = mcu_nextaddr_buf == 2'b01;
+
+assign mcu_rrq = mcu_rrq_r;
+assign mcu_wrq = mcu_wrq_r;
+assign mcu_write = SD_DMA_STATUS
+ ?(SD_DMA_TGTr == 2'b00
+ ?SD_DMA_SRAM_WE
+ :1'b1
+ )
+ : 1'b1;
+
+assign addr_out = ADDR_OUT_BUF;
+assign dac_addr_out = DAC_ADDR_OUT_BUF;
+assign msu_addr_out = MSU_ADDR_OUT_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 msu_reset_out = MSU_RESET_OUT_BUF;
+assign msu_ptr_out = MSU_PTR_OUT_BUF;
+
+assign bsx_regs_reset_we = bsx_regs_reset_we_buf;
+assign bsx_regs_reset_out = bsx_regs_reset_out_buf;
+assign bsx_regs_set_out = bsx_regs_set_out_buf;
+
+assign rtc_data_out = rtc_data_out_buf;
+assign rtc_pgm_we = rtc_pgm_we_buf;
+
+assign srtc_reset = srtc_reset_buf;
+
+assign mcu_data_out = SD_DMA_STATUS ? SD_DMA_SRAM_DATA : MCU_DATA_OUT_BUF;
+assign mcu_mapper = MAPPER_BUF;
+assign rom_mask_out = ROM_MASK;
+assign saveram_mask_out = SAVERAM_MASK;
+
+endmodule
diff --git a/verilog/sd2snes_test/sd2snes_test.xise b/verilog/sd2snes_test/sd2snes_test.xise
new file mode 100644
index 0000000..6c66fb1
--- /dev/null
+++ b/verilog/sd2snes_test/sd2snes_test.xise
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/verilog/sd2snes_test/sd_dma.v b/verilog/sd2snes_test/sd_dma.v
new file mode 100644
index 0000000..2137370
--- /dev/null
+++ b/verilog/sd2snes_test/sd_dma.v
@@ -0,0 +1,132 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 19:19:08 12/01/2010
+// Design Name:
+// Module Name: sd_dma
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module sd_dma(
+ input [3:0] SD_DAT,
+ inout SD_CLK,
+ input CLK,
+ input SD_DMA_EN,
+ output SD_DMA_STATUS,
+ output SD_DMA_SRAM_WE,
+ output SD_DMA_NEXTADDR,
+ 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[1:0] SD_DMA_DONEr2;
+initial begin
+ SD_DMA_DONEr2 = 2'b00;
+ SD_DMA_DONEr = 1'b0;
+end
+always @(posedge CLK) SD_DMA_DONEr2 <= {SD_DMA_DONEr2[0], SD_DMA_DONEr};
+wire SD_DMA_DONE_rising = (SD_DMA_DONEr2[1:0] == 2'b01);
+
+reg [1:0] SD_DMA_ENr;
+initial SD_DMA_ENr = 2'b00;
+always @(posedge CLK) SD_DMA_ENr <= {SD_DMA_ENr[0], SD_DMA_EN};
+wire SD_DMA_EN_rising = (SD_DMA_ENr [1:0] == 2'b01);
+
+reg SD_DMA_STATUSr;
+assign SD_DMA_STATUS = SD_DMA_STATUSr;
+
+// we need 1042 cycles (startbit + 1024 nibbles + 16 crc + stopbit)
+reg [10:0] cyclecnt;
+initial cyclecnt = 11'd0;
+
+reg SD_DMA_SRAM_WEr;
+initial SD_DMA_SRAM_WEr = 1'b1;
+assign SD_DMA_SRAM_WE = (cyclecnt < 1025 && SD_DMA_STATUSr) ? SD_DMA_SRAM_WEr : 1'b1;
+
+reg SD_DMA_NEXTADDRr;
+assign SD_DMA_NEXTADDR = (cyclecnt < 1025 && SD_DMA_STATUSr) ? SD_DMA_NEXTADDRr : 1'b0;
+
+reg[7:0] SD_DMA_SRAM_DATAr;
+assign SD_DMA_SRAM_DATA = SD_DMA_SRAM_DATAr;
+
+// we have 4 internal cycles per SD clock, 8 per RAM byte write
+reg [2:0] clkcnt;
+initial clkcnt = 3'b000;
+reg [1:0] SD_CLKr;
+always @(posedge CLK) SD_CLKr <= {SD_CLKr[0], clkcnt[1]};
+assign SD_CLK = SD_DMA_STATUSr ? SD_CLKr[1] : 1'bZ;
+
+always @(posedge CLK) begin
+ 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
+
+always @(posedge CLK) begin
+ if(cyclecnt == 1042) SD_DMA_DONEr <= 1;
+ else SD_DMA_DONEr <= 0;
+end
+
+always @(posedge CLK) begin
+ if(SD_DMA_EN_rising || !SD_DMA_STATUSr) begin
+ clkcnt <= 0;
+ end else begin
+ if(SD_DMA_STATUSr) begin
+ clkcnt <= clkcnt + 1;
+ end
+ end
+end
+
+always @(posedge CLK) begin
+ if(SD_DMA_EN_rising || !SD_DMA_STATUSr) cyclecnt <= 0;
+ else if(clkcnt[1:0] == 2'b11) cyclecnt <= cyclecnt + 1;
+end
+
+// we have 8 clk cycles to complete one RAM write
+// (4 clk cycles per SD_CLK; 2 SD_CLK cycles per byte)
+always @(posedge CLK) begin
+ if(SD_DMA_STATUSr) begin
+ case(clkcnt[2:0])
+ 3'h0: begin
+ SD_DMA_SRAM_WEr <= 1'b1;
+ SD_DMA_SRAM_DATAr[7:4] <= SD_DAT;
+ 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:
+ 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:
+// 3'h6:
+// 3'h7:
+ endcase
+ end
+end
+
+endmodule
+
diff --git a/verilog/sd2snes_test/spi.v b/verilog/sd2snes_test/spi.v
new file mode 100644
index 0000000..cb6bf79
--- /dev/null
+++ b/verilog/sd2snes_test/spi.v
@@ -0,0 +1,113 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 21:16:09 07/10/2009
+// Design Name:
+// Module Name: spi
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+
+//////////////////////////////////////////////////////////////////////////////////
+module spi(
+ input clk,
+ input SCK,
+ input MOSI,
+ inout MISO,
+ input SSEL,
+ output cmd_ready,
+ output param_ready,
+ output [7:0] cmd_data,
+ output [7:0] param_data,
+ output endmessage,
+ output startmessage,
+ input [7:0] input_data,
+ output [31:0] byte_cnt,
+ output [2:0] bit_cnt
+);
+
+reg [7:0] cmd_data_r;
+reg [7:0] param_data_r;
+
+reg [1:0] SSELr; always @(posedge clk) SSELr <= {SSELr[0], SSEL};
+wire SSEL_active = ~SSELr[1]; // SSEL is active low
+wire SSEL_startmessage = (SSELr[1:0]==2'b10); // message starts at falling edge
+wire SSEL_endmessage = (SSELr[1:0]==2'b01); // message stops at rising edge
+assign endmessage = SSEL_endmessage;
+assign startmessage = SSEL_startmessage;
+
+// bit count for one SPI byte + byte count for the message
+reg [2:0] bitcnt;
+reg [31:0] byte_cnt_r;
+
+reg byte_received; // high when a byte has been received
+reg [7:0] byte_data_received;
+
+assign bit_cnt = bitcnt;
+
+always @(posedge SCK) begin
+ if(SSEL) bitcnt <= 3'b000;
+ else begin
+ bitcnt <= bitcnt + 3'b001;
+ byte_data_received <= {byte_data_received[6:0], MOSI};
+ end
+ if(~SSEL && bitcnt==3'b111) byte_received <= 1'b1;
+ else byte_received <= 1'b0;
+end
+
+reg [1:0] byte_received_r;
+always @(posedge clk) byte_received_r <= {byte_received_r[0], byte_received};
+wire byte_received_sync = (byte_received_r == 2'b01);
+
+always @(posedge clk) begin
+ if(~SSEL_active)
+ byte_cnt_r <= 16'h0000;
+ else if(byte_received_sync) begin
+ byte_cnt_r <= byte_cnt_r + 16'h0001;
+ end
+end
+
+reg [7:0] byte_data_sent;
+
+assign MISO = ~SSEL ? input_data[7-bitcnt] : 1'bZ; // send MSB first
+
+reg cmd_ready_r;
+reg param_ready_r;
+reg cmd_ready_r2;
+reg param_ready_r2;
+assign cmd_ready = cmd_ready_r;
+assign param_ready = param_ready_r;
+assign cmd_data = cmd_data_r;
+assign param_data = param_data_r;
+assign byte_cnt = byte_cnt_r;
+
+always @(posedge clk) cmd_ready_r2 = byte_received_sync && byte_cnt_r == 32'h0;
+always @(posedge clk) param_ready_r2 = byte_received_sync && byte_cnt_r > 32'h0;
+
+// fill registers
+always @(posedge clk) begin
+ if (SSEL_startmessage)
+ cmd_data_r <= 8'h00;
+ else if(cmd_ready_r2)
+ cmd_data_r <= byte_data_received;
+ else if(param_ready_r2)
+ param_data_r <= byte_data_received;
+end
+
+// delay ready signals by one clock
+always @(posedge clk) begin
+ cmd_ready_r <= cmd_ready_r2;
+ param_ready_r <= param_ready_r2;
+end
+
+endmodule