From 3d05d075418898d002985af87146bcced65c54e4 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sat, 20 Jul 2024 21:40:26 -0700 Subject: [PATCH] Move shadow to us, get some commands going --- hw/super6502_fpga/sources.list | 2 +- hw/super6502_fpga/src/rtl/super_6502_fpga.sv | 6 +- hw/super6502_fpga/src/sim/hvl/sim_top.sv | 2 +- hw/super6502_fpga/src/sub/rtl-common | 2 +- .../sub/sd_controller_wrapper/shadow_regs.sv | 174 ++++++++++++++++++ sw/test_code/sd_controller_test/link.ld | 6 +- sw/test_code/sd_controller_test/main.s | 115 ++++++++++-- 7 files changed, 287 insertions(+), 20 deletions(-) create mode 100644 hw/super6502_fpga/src/sub/sd_controller_wrapper/shadow_regs.sv diff --git a/hw/super6502_fpga/sources.list b/hw/super6502_fpga/sources.list index 634b8f6..546ac0a 100644 --- a/hw/super6502_fpga/sources.list +++ b/hw/super6502_fpga/sources.list @@ -7,12 +7,12 @@ 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 -src/sub/rtl-common/src/rtl/shadow_regs.sv ip/sdram_controller/sdram_controller.v src/sub/wb2axip/rtl/axilxbar.v src/sub/wb2axip/rtl/addrdecode.v src/sub/wb2axip/rtl/skidbuffer.v src/sub/sd_controller_wrapper/sd_controller_wrapper.sv +src/sub/sd_controller_wrapper/shadow_regs.sv src/sub/sd_controller_wrapper/sdspi/rtl/sdckgen.v src/sub/sd_controller_wrapper/sdspi/rtl/sddma_rxgears.v src/sub/sd_controller_wrapper/sdspi/rtl/sddma.v diff --git a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv index efb88a2..2e877f0 100644 --- a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv +++ b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv @@ -243,7 +243,7 @@ axilxbar #( .NS(4), .SLAVE_ADDR({ {32'h000001ff, 32'h00000000}, - {32'h0000ffff, 32'h0000ff00}, + {32'h0000ffff, 32'h0000f000}, {32'h0000dfff, 32'h00000200}, {32'h0000e03f, 32'h0000e000} }) @@ -289,8 +289,8 @@ axilxbar #( ); axi4_lite_rom #( - .ROM_SIZE(8), - .BASE_ADDRESS(32'h0000ff00), + .ROM_SIZE(12), + .BASE_ADDRESS(32'h0000f000), .ROM_INIT_FILE("init_hex.mem") ) u_rom ( .i_clk(i_sysclk), diff --git a/hw/super6502_fpga/src/sim/hvl/sim_top.sv b/hw/super6502_fpga/src/sim/hvl/sim_top.sv index 4a4ac1c..4abf8e6 100644 --- a/hw/super6502_fpga/src/sim/hvl/sim_top.sv +++ b/hw/super6502_fpga/src/sim/hvl/sim_top.sv @@ -193,7 +193,7 @@ initial begin button_resetn <= '0; repeat(10) @(clk_cpu); button_resetn <= '1; - repeat(4000) @(posedge clk_cpu); + repeat(20000) @(posedge clk_cpu); $finish(); end diff --git a/hw/super6502_fpga/src/sub/rtl-common b/hw/super6502_fpga/src/sub/rtl-common index 96bf398..6bb56be 160000 --- a/hw/super6502_fpga/src/sub/rtl-common +++ b/hw/super6502_fpga/src/sub/rtl-common @@ -1 +1 @@ -Subproject commit 96bf398cf4fcdde2ee5570238c0e9ad13763bf72 +Subproject commit 6bb56be03a32ea76c7477e2403b396ede5818c31 diff --git a/hw/super6502_fpga/src/sub/sd_controller_wrapper/shadow_regs.sv b/hw/super6502_fpga/src/sub/sd_controller_wrapper/shadow_regs.sv new file mode 100644 index 0000000..0e5fc6b --- /dev/null +++ b/hw/super6502_fpga/src/sub/sd_controller_wrapper/shadow_regs.sv @@ -0,0 +1,174 @@ +module shadow_regs #( + parameter N = 8 +)( + input logic i_clk, + input logic i_reset, + + input logic S_AXIL_AWVALID, + output logic S_AXIL_AWREADY, + input logic [31:0] S_AXIL_AWADDR, + + input logic S_AXIL_WVALID, + output logic S_AXIL_WREADY, + input logic [31:0] S_AXIL_WDATA, + input logic [3:0] S_AXIL_WSTRB, + + output logic S_AXIL_BVALID, + input logic S_AXIL_BREADY, + output logic [1:0] S_AXIL_BRESP, + + input logic S_AXIL_ARVALID, + output logic S_AXIL_ARREADY, + input logic [31:0] S_AXIL_ARADDR, + + output logic S_AXIL_RVALID, + input logic S_AXIL_RREADY, + output logic [31:0] S_AXIL_RDATA, + output logic [1:0] S_AXIL_RRESP, + + output logic M_AXI_AWVALID, + input logic M_AXI_AWREADY, + output logic [31:0] M_AXI_AWADDR, + + output logic M_AXI_WVALID, + input logic M_AXI_WREADY, + output logic [31:0] M_AXI_WDATA, + output logic [3:0] M_AXI_WSTRB, + + input logic M_AXI_BVALID, + output logic M_AXI_BREADY, + input logic [1:0] M_AXI_BRESP, + + output logic M_AXI_ARVALID, + input logic M_AXI_ARREADY, + output logic [31:0] M_AXI_ARADDR, + + + input logic M_AXI_RVALID, + output logic M_AXI_RREADY, + input logic [31:0] M_AXI_RDATA, + input logic [1:0] M_AXI_RRESP +); + +assign M_AXI_ARVALID = S_AXIL_ARVALID; +assign S_AXIL_ARREADY = M_AXI_ARREADY; +assign M_AXI_ARADDR = S_AXIL_ARADDR; +assign S_AXIL_RVALID = M_AXI_RVALID; +assign M_AXI_RREADY = S_AXIL_RREADY; +assign S_AXIL_RDATA = M_AXI_RDATA; +assign S_AXIL_RRESP = M_AXI_RRESP; + + +logic [$clog2(N)-1:0] addr; + +logic [31:0] REGS [N]; +logic [31:0] prev; + +logic [31:0] prev_data; +logic [31:0] strobe_expanded; + + +logic addr_valid; +logic wdata_valid; +logic [31:0] wdata; + +logic passthrough; + +logic awready_seen; + +function automatic logic [31:0] strobe_expand(input logic [3:0] wstrb); + logic [31:0] expanded; + for (int i = 0; i < 4; i++) begin + expanded[i*8 +: 8] = {8{wstrb[i]}}; + end + + return expanded; +endfunction + +always_comb begin + S_AXIL_AWREADY = '0; + M_AXI_AWADDR = '0; + M_AXI_AWVALID = '0; + M_AXI_WVALID = '0; + M_AXI_WDATA = '0; + M_AXI_WSTRB = '0; + S_AXIL_WREADY = '0; + + M_AXI_BREADY = S_AXIL_BREADY; + S_AXIL_BVALID = M_AXI_BVALID; + S_AXIL_BRESP = M_AXI_BRESP; + + + if (S_AXIL_AWVALID && S_AXIL_WSTRB != 4'b0001) begin + S_AXIL_AWREADY = '1; + end + + if (S_AXIL_AWVALID && S_AXIL_WSTRB == 4'b0001) begin + M_AXI_AWVALID = '1; + S_AXIL_AWREADY = M_AXI_AWREADY; + end + + if (S_AXIL_WVALID && !passthrough) begin + S_AXIL_WREADY = '1; + S_AXIL_BVALID = '1; + end + + if (passthrough) begin + M_AXI_AWADDR = addr << 2; + M_AXI_AWVALID = ~awready_seen; + + M_AXI_WVALID = S_AXIL_WVALID; + S_AXIL_WREADY = M_AXI_WREADY; + M_AXI_WDATA = {REGS[addr][31:8], wdata[7:0]}; + M_AXI_WSTRB = {4'b111}; + M_AXI_WVALID = '1; + end +end + +always_ff @(posedge i_clk) begin + if (i_reset) begin + addr <= '0; + addr_valid <= '0; + prev_data <= '0; + strobe_expanded <= '0; + passthrough <= '0; + wdata_valid <= '0; + wdata <= '0; + awready_seen <= '0; + end else begin + if (S_AXIL_AWVALID) begin + addr <= S_AXIL_AWADDR[31:2]; + addr_valid <= '1; + prev_data <= REGS[S_AXIL_AWADDR[31:2]]; + end + + if (S_AXIL_WVALID) begin + passthrough <= S_AXIL_WSTRB == 4'b0001; + wdata <= S_AXIL_WDATA; + wdata_valid <= '1; + strobe_expanded <= strobe_expand(S_AXIL_WSTRB); + end + + if (wdata_valid && addr_valid) begin + REGS[addr] <= (prev_data & ~strobe_expanded) | wdata & strobe_expanded; + wdata_valid <= '0; + addr_valid <= '0; + end + + if (passthrough && M_AXI_WREADY) begin + passthrough <= '0; + end + + if (!passthrough) begin + awready_seen <= '0; + end + + if (M_AXI_AWREADY && M_AXI_AWVALID) begin + awready_seen <= '1; + end + + end +end + + +endmodule \ No newline at end of file diff --git a/sw/test_code/sd_controller_test/link.ld b/sw/test_code/sd_controller_test/link.ld index 44fc445..974a662 100644 --- a/sw/test_code/sd_controller_test/link.ld +++ b/sw/test_code/sd_controller_test/link.ld @@ -1,7 +1,7 @@ MEMORY { RAM: start = $0000, size = $200; - ROM: start = $FF00, size = $100, file = %O; + ROM: start = $F000, size = $1000, file = %O; } SEGMENTS { @@ -25,6 +25,6 @@ FEATURES { SYMBOLS { # Define the stack size for the application - __STACKSIZE__: value = $0200, type = weak; - __STACKSTART__: type = weak, value = $0800; # 2k stack + __STACKSIZE__: value = $0800, type = weak; + __STACKSTART__: type = weak, value = $0200; # 2k stack } diff --git a/sw/test_code/sd_controller_test/main.s b/sw/test_code/sd_controller_test/main.s index 82385fe..d2d8005 100644 --- a/sw/test_code/sd_controller_test/main.s +++ b/sw/test_code/sd_controller_test/main.s @@ -1,5 +1,9 @@ .export _init, _nmi_int, _irq_int +.include "zeropage.inc" + +.autoimport + .segment "VECTORS" .addr _nmi_int ; NMI vector @@ -10,6 +14,7 @@ SD_CONTROLLER = $e000 SD_CMD = SD_CONTROLLER SD_ARG = SD_CONTROLLER + $4 +SD_DATA = SD_ARG SD_FIFO_0 = SD_CONTROLLER + $8 SD_FIFO_2 = SD_CONTROLLER + $C @@ -39,6 +44,12 @@ _irq_int: _init: ldx #$ff txs + cld + + lda #<(__STACKSTART__ + __STACKSIZE__) + sta sp + lda #>(__STACKSTART__ + __STACKSIZE__) + sta sp+1 stz SD_PHY_CLKCTRL stz SD_PHY_SAMP_VOLT @@ -51,22 +62,50 @@ _init: cmp #SDIOCLK_100KHZ bne @wait_clk - stz SD_CMD+$3 - lda #$04 - sta SD_CMD+$2 + ; send_goidle(); + jsr send_goidle + + ; send_r1(8, 0x1aa); + lda #$0 + sta sreg+1 + lda #$0 + sta sreg + ldx #$01 + lda #$aa + jsr pusheax lda #$08 - sta SD_CMD+$1 + jsr send_r1 + +@acmd41: + ; send_r1(55, 0x00); + lda #$0 + sta sreg+1 + lda #$0 + sta sreg + ldx #$00 + lda #$00 + jsr pusheax + lda #55 + jsr send_r1 + + ; send_r1(41, 0x4000ff80); lda #$40 - sta SD_CMD + sta sreg+1 + lda #$0 + sta sreg + ldx #$ff + lda #$80 + jsr pusheax + lda #41 + jsr send_r1 - jsr wait_busy + lda sreg+1 + bpl @acmd41 - lda #$01 - sta SD_CMD+$1 - lda #$48 - sta SD_CMD + ; cmd 11 + ; cmd 2 + ; cmd 3 - jsr wait_busy @end: bra @end @@ -75,4 +114,58 @@ _init: wait_busy: lda SD_CMD+$1 bit #$40 bne wait_busy + rts + + +; No arguments, no response +; sends cmd0 +; also clears removed and error flags? +send_goidle: + stz SD_ARG+$3 + stz SD_ARG+$2 + stz SD_ARG+$1 + stz SD_ARG + + stz SD_CMD+$3 + lda #$04 + sta SD_CMD+$2 + lda #$80 + sta SD_CMD+$1 + lda #$40 + sta SD_CMD + + jsr wait_busy + + rts + +; Command in A +; Arg on stack as 32 bits +; returns the response in eax +; (How can we signal a failure then?) +send_r1: + pha ; push command to stack + jsr popeax + PHA + stx SD_ARG+$1 + lda sreg + sta SD_ARG+$2 + lda sreg+1 + sta SD_ARG+$3 + pla + sta SD_ARG ; lsb has to be the last written. + lda #$81 ; This also clears error flag (only for acmd41?) + sta SD_CMD+$1 + pla + ora #$40 + sta SD_CMD + + jsr wait_busy + + lda SD_DATA + $3 + sta sreg+1 + lda SD_DATA + $2 + sta sreg + ldx SD_DATA + $1 + lda SD_DATA + rts \ No newline at end of file