diff --git a/.gitmodules b/.gitmodules
index 90e702c..4ac190d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,3 +10,9 @@
[submodule "hw/super6502_fpga/src/sim/sub/verilog-6502"]
path = hw/super6502_fpga/src/sim/sub/verilog-6502
url = ../verilog-6502.git
+[submodule "hw/super6502_fpga/src/sub/sd_controller"]
+ path = hw/super6502_fpga/src/sub/sd_controller
+ url = ../sd_controller.git
+[submodule "hw/super6502_fpga/src/sim/sub/verilog-sd-emulator"]
+ path = hw/super6502_fpga/src/sim/sub/verilog-sd-emulator
+ url = ../verilog-sd-emulator.git
diff --git a/Makefile b/Makefile
index f13bfba..96f4ed7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,9 @@
-ROM_TARGET=test_code/loop_test
+ROM_TARGET=test_code/sd_controller_test
INIT_HEX=hw/super6502_fpga/init_hex.mem
HEX=sw/$(ROM_TARGET)/$(notdir $(ROM_TARGET)).bin
+CC65=sw/toolchain/cc65/bin
all: fpga_image
@@ -14,15 +15,17 @@ fpga_image: $(INIT_HEX)
sim: $(INIT_HEX)
$(MAKE) -C hw/super6502_fpga/src/sim
+pgm:
+ $(MAKE) -C hw/super6502_fpga pgm
+
waves: sim
gtkwave hw/super6502_fpga/src/sim/sim_top.vcd
# SW
-.PHONY: toolchain
-toolchain:
+$(CC65):
$(MAKE) -C sw/toolchain/cc65 -j $(shell nproc)
-$(INIT_HEX): toolchain script/generate_rom_image.py $(HEX)
+$(INIT_HEX): $(CC65) script/generate_rom_image.py $(HEX)
python script/generate_rom_image.py -i $(HEX) -o $@
$(HEX):
diff --git a/hw/super6502_fpga/Makefile b/hw/super6502_fpga/Makefile
index 8b16685..bf0d84c 100644
--- a/hw/super6502_fpga/Makefile
+++ b/hw/super6502_fpga/Makefile
@@ -9,7 +9,11 @@ all: $(SUPER6502_FPGA_BITSTREAM)
$(SUPER6502_FPGA_BITSTREAM): $(SUPER6502_FPGA_SOURCES) $(SUPER6502_FPGA_PROJECT)
efx_run.py $(SUPER6502_FPGA_PROJECT)
+pgm:
+ efx_run.py $(SUPER6502_FPGA_PROJECT) --flow program --pgm_opts mode=jtag
+
.PHONY: clean
clean:
rm -rf work_*
- rm -rf outflow
\ No newline at end of file
+ rm -rf outflow
+ rm -rf init_hex.mem
diff --git a/hw/super6502_fpga/addr_map.mem b/hw/super6502_fpga/addr_map.mem
index 7a02cdc..d10710d 100644
--- a/hw/super6502_fpga/addr_map.mem
+++ b/hw/super6502_fpga/addr_map.mem
@@ -4,4 +4,6 @@
0000ff00
0000ffff
00000200
-0000efff
\ No newline at end of file
+0000dfff
+0000e000
+0000e03f
\ No newline at end of file
diff --git a/hw/super6502_fpga/sources.list b/hw/super6502_fpga/sources.list
index b9113d1..0ef340c 100644
--- a/hw/super6502_fpga/sources.list
+++ b/hw/super6502_fpga/sources.list
@@ -11,4 +11,14 @@ src/sub/rtl-common/src/rtl/axi4_lite_rom.sv
src/sub/rtl-common/src/rtl/ff_cdc.sv
src/sub/rtl-common/src/rtl/shallow_async_fifo.sv
src/sub/rtl-common/src/rtl/sync_fifo.sv
+src/sub/rtl-common/src/rtl/axi4_lite_to_apb4.sv
ip/sdram_controller/sdram_controller.v
+src/sub/sd_controller/src/regs/sd_controller_regs_pkg.sv
+src/sub/sd_controller/src/regs/sd_controller_regs.sv
+src/sub/sd_controller/src/crc7.sv
+src/sub/sd_controller/src/crc16.sv
+src/sub/sd_controller/src/sd_command.sv
+src/sub/sd_controller/src/sd_control.sv
+src/sub/sd_controller/src/sd_controller_top.sv
+src/sub/sd_controller/src/sd_data.sv
+src/sub/sd_controller/src/sd_dma.sv
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
index 84cdee6..a1fae5c 100644
--- a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
+++ b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
@@ -35,7 +35,16 @@ module super6502_fpga(
output logic o_cpu0_nmib,
output logic o_cpu0_rdy,
output logic o_cpu0_reset,
- output logic o_clk_phi2
+ output logic o_clk_phi2,
+
+ input i_sd_cmd,
+ output o_sd_cmd,
+ output o_sd_cmd_oe,
+ input i_sd_dat,
+ output o_sd_dat,
+ output o_sd_dat_oe,
+ output o_sd_clk,
+ output o_sd_cs
);
@@ -66,6 +75,8 @@ assign sdram_ready = |w_sdr_state;
assign master_reset = pre_reset & sdram_ready;
+assign o_sd_cs = '1;
+
logic cpu0_AWVALID;
logic cpu0_AWREADY;
@@ -141,6 +152,45 @@ logic [DATA_WIDTH-1:0] sdram_RDATA;
logic [1:0] sdram_RRESP;
+// These are for the control/status registers
+logic sd_controller_csr_AWVALID;
+logic sd_controller_csr_AWREADY;
+logic [ADDR_WIDTH-1:0] sd_controller_csr_AWADDR;
+logic sd_controller_csr_WVALID;
+logic sd_controller_csr_WREADY;
+logic [DATA_WIDTH-1:0] sd_controller_csr_WDATA;
+logic [DATA_WIDTH/8-1:0] sd_controller_csr_WSTRB;
+logic sd_controller_csr_BVALID;
+logic sd_controller_csr_BREADY;
+logic [1:0] sd_controller_csr_BRESP;
+logic sd_controller_csr_ARVALID;
+logic sd_controller_csr_ARREADY;
+logic [ADDR_WIDTH-1:0] sd_controller_csr_ARADDR;
+logic sd_controller_csr_RVALID;
+logic sd_controller_csr_RREADY;
+logic [DATA_WIDTH-1:0] sd_controller_csr_RDATA;
+logic [1:0] sd_controller_csr_RRESP;
+
+// these are for the dma master.
+logic sd_controller_dma_AWVALID;
+logic sd_controller_dma_AWREADY;
+logic [ADDR_WIDTH-1:0] sd_controller_dma_AWADDR;
+logic sd_controller_dma_WVALID;
+logic sd_controller_dma_WREADY;
+logic [DATA_WIDTH-1:0] sd_controller_dma_WDATA;
+logic [DATA_WIDTH/8-1:0] sd_controller_dma_WSTRB;
+logic sd_controller_dma_BVALID;
+logic sd_controller_dma_BREADY;
+logic [1:0] sd_controller_dma_BRESP;
+logic sd_controller_dma_ARVALID;
+logic sd_controller_dma_ARREADY;
+logic [ADDR_WIDTH-1:0] sd_controller_dma_ARADDR;
+logic sd_controller_dma_RVALID;
+logic sd_controller_dma_RREADY;
+logic [DATA_WIDTH-1:0] sd_controller_dma_RDATA;
+logic [1:0] sd_controller_dma_RRESP;
+
+
cpu_wrapper u_cpu_wrapper_0(
.i_clk_cpu (clk_cpu),
.i_clk_100 (i_sysclk),
@@ -186,47 +236,46 @@ cpu_wrapper u_cpu_wrapper_0(
axi_crossbar #(
- .N_INITIATORS(1),
- .N_TARGETS(3)
+ .N_INITIATORS(2),
+ .N_TARGETS(4)
) u_crossbar (
.clk(i_sysclk),
.rst(~master_reset),
- .ini_araddr ({cpu0_ARADDR }),
- .ini_arvalid ({cpu0_ARVALID }),
- .ini_arready ({cpu0_ARREADY }),
- .ini_rdata ({cpu0_RDATA }),
- .ini_rresp ({cpu0_RRESP }),
- .ini_rvalid ({cpu0_RVALID }),
- .ini_rready ({cpu0_RREADY }),
- .ini_awaddr ({cpu0_AWADDR }),
- .ini_awready ({cpu0_AWREADY }),
- .ini_awvalid ({cpu0_AWVALID }),
- .ini_wvalid ({cpu0_WVALID }),
- .ini_wready ({cpu0_WREADY }),
- .ini_wdata ({cpu0_WDATA }),
- .ini_wstrb ({cpu0_WSTRB }),
- .ini_bresp ({cpu0_BRESP }),
- .ini_bvalid ({cpu0_BVALID }),
- .ini_bready ({cpu0_BREADY }),
-
- .tgt_araddr ({ram_araddr, rom_araddr, sdram_ARADDR }),
- .tgt_arvalid ({ram_arvalid, rom_arvalid, sdram_ARVALID }),
- .tgt_arready ({ram_arready, rom_arready, sdram_ARREADY }),
- .tgt_rdata ({ram_rdata, rom_rdata, sdram_RDATA }),
- .tgt_rresp ({ram_rresp, rom_rresp, sdram_RRESP }),
- .tgt_rvalid ({ram_rvalid, rom_rvalid, sdram_RVALID }),
- .tgt_rready ({ram_rready, rom_rready, sdram_RREADY }),
- .tgt_awaddr ({ram_awaddr, rom_awaddr, sdram_AWADDR }),
- .tgt_awvalid ({ram_awvalid, rom_awvalid, sdram_AWVALID }),
- .tgt_awready ({ram_awready, rom_awready, sdram_AWREADY }),
- .tgt_wdata ({ram_wdata, rom_wdata, sdram_WDATA }),
- .tgt_wvalid ({ram_wvalid, rom_wvalid, sdram_WVALID }),
- .tgt_wready ({ram_wready, rom_wready, sdram_WREADY }),
- .tgt_wstrb ({ram_wstrb, rom_wstrb, sdram_WSTRB }),
- .tgt_bresp ({ram_bresp, rom_bresp, sdram_BRESP }),
- .tgt_bvalid ({ram_bvalid, rom_bvalid, sdram_BVALID }),
- .tgt_bready ({ram_bready, rom_bready, sdram_BREADY })
+ .ini_araddr ({cpu0_ARADDR, sd_controller_dma_ARADDR }),
+ .ini_arvalid ({cpu0_ARVALID, sd_controller_dma_ARVALID }),
+ .ini_arready ({cpu0_ARREADY, sd_controller_dma_ARREADY }),
+ .ini_rdata ({cpu0_RDATA, sd_controller_dma_RDATA }),
+ .ini_rresp ({cpu0_RRESP, sd_controller_dma_RRESP }),
+ .ini_rvalid ({cpu0_RVALID, sd_controller_dma_RVALID }),
+ .ini_rready ({cpu0_RREADY, sd_controller_dma_RREADY }),
+ .ini_awaddr ({cpu0_AWADDR, sd_controller_dma_AWADDR }),
+ .ini_awready ({cpu0_AWREADY, sd_controller_dma_AWREADY }),
+ .ini_awvalid ({cpu0_AWVALID, sd_controller_dma_AWVALID }),
+ .ini_wvalid ({cpu0_WVALID, sd_controller_dma_WVALID }),
+ .ini_wready ({cpu0_WREADY, sd_controller_dma_WREADY }),
+ .ini_wdata ({cpu0_WDATA, sd_controller_dma_WDATA }),
+ .ini_wstrb ({cpu0_WSTRB, sd_controller_dma_WSTRB }),
+ .ini_bresp ({cpu0_BRESP, sd_controller_dma_BRESP }),
+ .ini_bvalid ({cpu0_BVALID, sd_controller_dma_BVALID }),
+ .ini_bready ({cpu0_BREADY, sd_controller_dma_BREADY }),
+ .tgt_araddr ({ram_araddr, rom_araddr, sdram_ARADDR, sd_controller_csr_ARADDR }),
+ .tgt_arvalid ({ram_arvalid, rom_arvalid, sdram_ARVALID, sd_controller_csr_ARVALID }),
+ .tgt_arready ({ram_arready, rom_arready, sdram_ARREADY, sd_controller_csr_ARREADY }),
+ .tgt_rdata ({ram_rdata, rom_rdata, sdram_RDATA, sd_controller_csr_RDATA }),
+ .tgt_rresp ({ram_rresp, rom_rresp, sdram_RRESP, sd_controller_csr_RRESP }),
+ .tgt_rvalid ({ram_rvalid, rom_rvalid, sdram_RVALID, sd_controller_csr_RVALID }),
+ .tgt_rready ({ram_rready, rom_rready, sdram_RREADY, sd_controller_csr_RREADY }),
+ .tgt_awaddr ({ram_awaddr, rom_awaddr, sdram_AWADDR, sd_controller_csr_AWADDR }),
+ .tgt_awvalid ({ram_awvalid, rom_awvalid, sdram_AWVALID, sd_controller_csr_AWVALID }),
+ .tgt_awready ({ram_awready, rom_awready, sdram_AWREADY, sd_controller_csr_AWREADY }),
+ .tgt_wdata ({ram_wdata, rom_wdata, sdram_WDATA, sd_controller_csr_WDATA }),
+ .tgt_wvalid ({ram_wvalid, rom_wvalid, sdram_WVALID, sd_controller_csr_WVALID }),
+ .tgt_wready ({ram_wready, rom_wready, sdram_WREADY, sd_controller_csr_WREADY }),
+ .tgt_wstrb ({ram_wstrb, rom_wstrb, sdram_WSTRB, sd_controller_csr_WSTRB }),
+ .tgt_bresp ({ram_bresp, rom_bresp, sdram_BRESP, sd_controller_csr_BRESP }),
+ .tgt_bvalid ({ram_bvalid, rom_bvalid, sdram_BVALID, sd_controller_csr_BVALID }),
+ .tgt_bready ({ram_bready, rom_bready, sdram_BREADY, sd_controller_csr_BREADY })
);
@@ -368,6 +417,96 @@ sdram_controller u_sdram_controller(
.o_sdr_DQM (w_sdr_DQM)
);
+logic sd_controller_apb_psel;
+logic sd_controller_apb_penable;
+logic sd_controller_apb_pwrite;
+logic [2:0] sd_controller_apb_pprot;
+logic [ADDR_WIDTH-1:0] sd_controller_apb_paddr;
+logic [DATA_WIDTH-1:0] sd_controller_apb_pwdata;
+logic [DATA_WIDTH/8-1:0] sd_controller_apb_pstrb;
+logic sd_controller_apb_pready;
+logic [DATA_WIDTH-1:0] sd_controller_apb_prdata;
+logic sd_controller_apb_pslverr;
+axi4_lite_to_apb4 u_sd_axi_apb_converter (
+ .i_clk(i_sysclk),
+ .i_rst(~master_reset),
+
+ .i_AWVALID(sd_controller_csr_AWVALID),
+ .o_AWREADY(sd_controller_csr_AWREADY),
+ .i_AWADDR(sd_controller_csr_AWADDR),
+ .i_WVALID(sd_controller_csr_AWVALID),
+ .o_WREADY(sd_controller_csr_WREADY),
+ .i_WDATA(sd_controller_csr_WDATA),
+ .i_WSTRB(sd_controller_csr_WSTRB),
+ .o_BVALID(sd_controller_csr_BVALID),
+ .i_BREADY(sd_controller_csr_BREADY),
+ .o_BRESP(sd_controller_csr_BRESP),
+ .i_ARVALID(sd_controller_csr_ARVALID),
+ .o_ARREADY(sd_controller_csr_ARREADY),
+ .i_ARADDR(sd_controller_csr_ARADDR),
+ .i_ARPROT('0),
+ .o_RVALID(sd_controller_csr_RVALID),
+ .i_RREADY(sd_controller_csr_RREADY),
+ .o_RDATA(sd_controller_csr_RDATA),
+ .o_RRESP(sd_controller_csr_RRESP),
+
+ .m_apb_psel(sd_controller_apb_psel),
+ .m_apb_penable(sd_controller_apb_penable),
+ .m_apb_pwrite(sd_controller_apb_pwrite),
+ .m_apb_pprot(sd_controller_apb_pprot),
+ .m_apb_paddr(sd_controller_apb_paddr),
+ .m_apb_pwdata(sd_controller_apb_pwdata),
+ .m_apb_pstrb(sd_controller_apb_pstrb),
+ .m_apb_pready(sd_controller_apb_pready),
+ .m_apb_prdata(sd_controller_apb_prdata),
+ .m_apb_pslverr(sd_controller_apb_pslverr)
+);
+
+sd_controller_top u_sd_controller (
+ .clk(i_sysclk),
+ .rst(~master_reset),
+
+ .s_apb_psel(sd_controller_apb_psel),
+ .s_apb_penable(sd_controller_apb_penable),
+ .s_apb_pwrite(sd_controller_apb_pwrite),
+ .s_apb_pprot(sd_controller_apb_pprot),
+ .s_apb_paddr(sd_controller_apb_paddr[5:0]),
+ .s_apb_pwdata(sd_controller_apb_pwdata),
+ .s_apb_pstrb(sd_controller_apb_pstrb),
+ .s_apb_pready(sd_controller_apb_pready),
+ .s_apb_prdata(sd_controller_apb_prdata),
+ .s_apb_pslverr(sd_controller_apb_pslverr),
+
+ .o_AWVALID (sd_controller_dma_AWVALID),
+ .i_AWREADY (sd_controller_dma_AWREADY),
+ .o_AWADDR (sd_controller_dma_AWADDR),
+ .o_WVALID (sd_controller_dma_WVALID),
+ .i_WREADY (sd_controller_dma_WREADY),
+ .o_WDATA (sd_controller_dma_WDATA),
+ .o_WSTRB (sd_controller_dma_WSTRB),
+ .i_BVALID (sd_controller_dma_BVALID),
+ .o_BREADY (sd_controller_dma_BREADY),
+ .i_BRESP (sd_controller_dma_BRESP),
+ .o_ARVALID (sd_controller_dma_ARVALID),
+ .i_ARREADY (sd_controller_dma_ARREADY),
+ .o_ARADDR (sd_controller_dma_ARADDR),
+ .i_RVALID (sd_controller_dma_RVALID),
+ .o_RREADY (sd_controller_dma_RREADY),
+ .i_RDATA (sd_controller_dma_RDATA),
+ .i_RRESP (sd_controller_dma_RRESP),
+
+
+
+ .i_sd_cmd(i_sd_cmd),
+ .o_sd_cmd(o_sd_cmd),
+ .o_sd_cmd_oe(o_sd_cmd_oe),
+ .o_sd_clk(o_sd_clk),
+
+ .i_sd_dat(i_sd_dat),
+ .o_sd_dat(o_sd_dat),
+ .o_sd_dat_oe(o_sd_dat_oe)
+);
+
endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sim/hvl/sim_top.sv b/hw/super6502_fpga/src/sim/hvl/sim_top.sv
index c4c29c8..c8ba47e 100644
--- a/hw/super6502_fpga/src/sim/hvl/sim_top.sv
+++ b/hw/super6502_fpga/src/sim/hvl/sim_top.sv
@@ -39,7 +39,7 @@ initial begin
clk_cpu <= '1;
forever begin
// #62.5 clk_cpu <= ~clk_cpu;
- #250 clk_cpu <= ~clk_cpu;
+ #500 clk_cpu <= ~clk_cpu;
end
end
@@ -59,9 +59,10 @@ logic w_cpu0_rdy;
logic w_cpu0_irqb;
logic w_cpu0_we;
logic w_cpu0_sync;
+logic w_clk_phi2;
cpu_65c02 u_cpu0 (
- .phi2 (clk_cpu),
+ .phi2 (w_clk_phi2),
.reset (~w_cpu0_reset),
.AB (w_cpu0_addr),
.RDY (w_cpu0_rdy),
@@ -111,6 +112,18 @@ generate
end
endgenerate
+
+// potential sd card sim here?
+
+logic i_sd_cmd;
+logic o_sd_cmd;
+logic o_sd_cmd_oe;
+logic i_sd_dat;
+logic o_sd_dat;
+logic i_sd_dat_oe;
+logic o_sd_clk;
+logic o_sd_cs;
+
super6502_fpga u_dut (
.i_sysclk (clk_100),
.i_sdrclk (clk_200),
@@ -127,6 +140,7 @@ super6502_fpga u_dut (
.o_cpu0_irqb (w_cpu0_irqb),
.i_cpu0_rwb (~w_cpu0_we),
.i_cpu0_sync (w_cpu0_sync),
+ .o_clk_phi2 (w_clk_phi2),
.o_sdr_CKE (w_sdr_CKE),
.o_sdr_n_CS (w_sdr_n_CS),
@@ -138,8 +152,25 @@ super6502_fpga u_dut (
.i_sdr_DATA (w_sdr_DQ),
.o_sdr_DATA (w_sdr_DATA),
.o_sdr_DATA_oe (w_sdr_DATA_oe),
- .o_sdr_DQM (w_sdr_DQM)
+ .o_sdr_DQM (w_sdr_DQM),
+ .i_sd_cmd (i_sd_cmd),
+ .o_sd_cmd (o_sd_cmd),
+ .o_sd_cmd_oe (o_sd_cmd_oe),
+ .i_sd_dat (i_sd_dat),
+ .o_sd_dat (o_sd_dat),
+ .o_sd_dat_oe (o_sd_dat_oe),
+ .o_sd_clk (o_sd_clk),
+ .o_sd_cs (o_sd_cs)
+);
+
+sd_card_emu u_sd_card_emu(
+ .clk(o_sd_clk),
+ .rst(~button_reset),
+ .i_cmd(o_sd_cmd),
+ .o_cmd(i_sd_cmd),
+ .i_dat(o_sd_dat),
+ .o_dat(i_sd_dat)
);
initial begin
diff --git a/hw/super6502_fpga/src/sim/sources.list b/hw/super6502_fpga/src/sim/sources.list
index fd86d41..76909da 100644
--- a/hw/super6502_fpga/src/sim/sources.list
+++ b/hw/super6502_fpga/src/sim/sources.list
@@ -1,4 +1,8 @@
hvl/sim_top.sv
sub/verilog-6502/ALU.v
sub/verilog-6502/cpu_65c02.v
-sub/sim_sdram/generic_sdr.v
\ No newline at end of file
+sub/sim_sdram/generic_sdr.v
+sub/verilog-sd-emulator/src/sd_card_command.sv
+sub/verilog-sd-emulator/src/sd_card_emu.sv
+sub/verilog-sd-emulator/src/sd_card_state_controller.sv
+sub/verilog-sd-emulator/src/sd_card_data.sv
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sim/sub/verilog-sd-emulator b/hw/super6502_fpga/src/sim/sub/verilog-sd-emulator
new file mode 160000
index 0000000..265c636
--- /dev/null
+++ b/hw/super6502_fpga/src/sim/sub/verilog-sd-emulator
@@ -0,0 +1 @@
+Subproject commit 265c636c86076662e1b6405dd47a71a6077d51d0
diff --git a/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv b/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv
index b0a20fd..51958e5 100644
--- a/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv
+++ b/hw/super6502_fpga/src/sub/cpu_wrapper/cpu_wrapper.sv
@@ -207,7 +207,7 @@ always @(posedge i_clk_100 or posedge i_rst) begin
end
end
-localparam MAX_DELAY = 4;
+localparam MAX_DELAY = 8;
logic [7:0] cycle_counter;
logic too_late;
diff --git a/hw/super6502_fpga/src/sub/rtl-common b/hw/super6502_fpga/src/sub/rtl-common
index 170285d..401042b 160000
--- a/hw/super6502_fpga/src/sub/rtl-common
+++ b/hw/super6502_fpga/src/sub/rtl-common
@@ -1 +1 @@
-Subproject commit 170285d7abf968dbe9cb6f3d919039bc117eef60
+Subproject commit 401042bb0ff9db0f44dab9cb6e08c71058a1bcb1
diff --git a/hw/super6502_fpga/src/sub/sd_controller b/hw/super6502_fpga/src/sub/sd_controller
new file mode 160000
index 0000000..a16ffb4
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/sd_controller
@@ -0,0 +1 @@
+Subproject commit a16ffb427c6ac8857fd14b6fb9fe1614399b3cbc
diff --git a/hw/super6502_fpga/super6502_fpga.peri.xml b/hw/super6502_fpga/super6502_fpga.peri.xml
index 2141ac8..b9051f9 100644
--- a/hw/super6502_fpga/super6502_fpga.peri.xml
+++ b/hw/super6502_fpga/super6502_fpga.peri.xml
@@ -282,7 +282,22 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hw/super6502_fpga/super6502_fpga.xml b/hw/super6502_fpga/super6502_fpga.xml
index 1dcda00..cb3545b 100644
--- a/hw/super6502_fpga/super6502_fpga.xml
+++ b/hw/super6502_fpga/super6502_fpga.xml
@@ -1,4 +1,4 @@
-
+
@@ -16,6 +16,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -86,4 +97,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/init_env.sh b/init_env.sh
index 5832a54..0bac1ed 100644
--- a/init_env.sh
+++ b/init_env.sh
@@ -8,14 +8,14 @@ export KICAD7_SYMBOL_DIR=$REPO_TOP/hw/kicad_library/symbols
export KICAD7_3DMODEL_DIR=$REPO_TOP/hw/kicad_library/3dmodels
export KICAD7_FOOTPRINT_DIR=$REPO_TOP/hw/kicad_library/footprints
+
+python3.11 -m venv .user_venv
+. .user_venv/bin/activate
+
if [ -n "$EFX_SETUP" ]; then
source $EFX_SETUP
else
echo "EFX_SETUP not defined!"
fi
-
-python3 -m venv .user_venv
-. .user_venv/bin/activate
-
# pip install -r requirements.txt
diff --git a/sw/test_code/sd_controller_test/Makefile b/sw/test_code/sd_controller_test/Makefile
new file mode 100644
index 0000000..ebdce77
--- /dev/null
+++ b/sw/test_code/sd_controller_test/Makefile
@@ -0,0 +1,39 @@
+CC=../../toolchain/cc65/bin/cl65
+LD=../../toolchain/cc65/bin/cl65
+CFLAGS=-T -t none -I. --cpu "65C02"
+LDFLAGS=-C link.ld -m $(NAME).map
+
+NAME=sd_controller_test
+
+BIN=$(NAME).bin
+HEX=$(NAME).hex
+
+LISTS=lists
+
+SRCS=$(wildcard *.s) $(wildcard *.c)
+SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
+OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
+OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
+
+# Make sure the kernel linked to correct address, no relocation!
+all: $(HEX)
+
+$(HEX): $(BIN)
+ objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX)
+
+$(BIN): $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+%.o: %.c $(LISTS)
+ $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
+
+%.o: %.s $(LISTS)
+ $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
+
+$(LISTS):
+ mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
+
+.PHONY: clean
+clean:
+ rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
+
diff --git a/sw/test_code/sd_controller_test/link.ld b/sw/test_code/sd_controller_test/link.ld
new file mode 100644
index 0000000..44fc445
--- /dev/null
+++ b/sw/test_code/sd_controller_test/link.ld
@@ -0,0 +1,30 @@
+MEMORY
+{
+ RAM: start = $0000, size = $200;
+ ROM: start = $FF00, size = $100, file = %O;
+}
+
+SEGMENTS {
+ ZEROPAGE: load = RAM, type = zp, define = yes;
+ DATA: load = ROM, type = rw, define = yes;
+ CODE: load = ROM, type = ro;
+ RODATA: load = ROM, type = ro;
+ VECTORS: load = ROM, type = ro, start = $FFFA;
+}
+
+FEATURES {
+ CONDES: segment = STARTUP,
+ type = constructor,
+ label = __CONSTRUCTOR_TABLE__,
+ count = __CONSTRUCTOR_COUNT__;
+ CONDES: segment = STARTUP,
+ type = destructor,
+ label = __DESTRUCTOR_TABLE__,
+ count = __DESTRUCTOR_COUNT__;
+}
+
+SYMBOLS {
+ # Define the stack size for the application
+ __STACKSIZE__: value = $0200, type = weak;
+ __STACKSTART__: type = weak, value = $0800; # 2k stack
+}
diff --git a/sw/test_code/sd_controller_test/main.s b/sw/test_code/sd_controller_test/main.s
new file mode 100644
index 0000000..8576a2a
--- /dev/null
+++ b/sw/test_code/sd_controller_test/main.s
@@ -0,0 +1,139 @@
+.export _init, _nmi_int, _irq_int
+
+.segment "VECTORS"
+
+.addr _nmi_int ; NMI vector
+.addr _init ; Reset vector
+.addr _irq_int ; IRQ/BRK vector
+
+SD_CONTROLLER = $e000
+SD_ARG = SD_CONTROLLER + $4
+SD_RESP = SD_CONTROLLER + $10
+CLK_DIV = $20
+
+SD_DMA_BASE = SD_CONTROLLER + $28
+SD_DMA_STAT_CTRL = SD_CONTROLLER + $2C
+
+.zeropage
+rca: .res 4
+
+.code
+
+_nmi_int:
+_irq_int:
+
+_init:
+ ldx #$ff
+ txs
+
+ lda #$00
+ sta SD_CONTROLLER
+
+ lda #$aa
+ sta SD_ARG
+ lda #$01
+ sta SD_ARG+1
+ lda #$00
+ sta SD_ARG+2
+ sta SD_ARG+3
+ lda #$08
+ sta SD_CONTROLLER
+ jsr delay
+
+ lda #55
+ sta SD_CONTROLLER
+ jsr delay
+ lda #41
+ sta SD_CONTROLLER
+ jsr delay
+
+@acmd41:
+ lda #55
+ sta SD_CONTROLLER
+
+ jsr delay
+
+ lda #$80
+ sta SD_ARG+1
+ lda #$ff
+ sta SD_ARG+2
+ lda #$40
+ sta SD_ARG+3
+ lda #41
+ sta SD_CONTROLLER
+
+ jsr delay
+
+ lda SD_RESP+3
+ bmi card_ready
+
+
+ ldx #$10
+@loop: dex
+ bne @loop
+
+ bra @acmd41
+
+card_ready:
+ lda #2
+ sta SD_CONTROLLER
+
+ jsr delay
+
+ lda #3
+ sta SD_CONTROLLER
+
+ jsr delay
+
+ lda SD_RESP
+ sta rca
+ lda SD_RESP+1
+ sta rca+1
+ lda SD_RESP+2
+ sta rca+2
+ lda SD_RESP+3
+ sta rca+3
+
+ lda rca
+ sta SD_ARG
+ lda rca+1
+ sta SD_ARG+1
+ lda rca+2
+ sta SD_ARG+2
+ lda rca+3
+ sta SD_ARG+3
+ lda #7
+ sta SD_CONTROLLER
+
+ jsr delay
+
+ lda #17
+ sta SD_CONTROLLER
+
+ lda #$10
+ sta SD_DMA_BASE + 1
+ lda #1
+ sta SD_DMA_STAT_CTRL
+
+@poll: lda SD_DMA_STAT_CTRL+2
+ cmp #$1
+ bne @poll
+ stz SD_DMA_STAT_CTRL
+
+ lda $1000
+ lda $1001
+ lda $1002
+ lda $1003
+
+
+@end: bra @end
+
+delay:
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ rts
\ No newline at end of file