From 7cfbcd55140124efa4871a6b40b5559eb824c6f7 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Aug 2021 06:41:45 +1000 Subject: [PATCH] litesdcard: Add Nexys Video support This board has a reset line that needs to be held low to power up the SD card hardware. Signed-off-by: Anton Blanchard --- fpga/nexys-video.xdc | 16 +++++ fpga/top-nexys-video.vhdl | 143 +++++++++++++++++++++++++++++++++++++- microwatt.core | 9 ++- 3 files changed, 163 insertions(+), 5 deletions(-) diff --git a/fpga/nexys-video.xdc b/fpga/nexys-video.xdc index f04c4da..7109c73 100644 --- a/fpga/nexys-video.xdc +++ b/fpga/nexys-video.xdc @@ -41,6 +41,22 @@ set_property -dict { PACKAGE_PIN R22 IOSTANDARD LVCMOS33 } [get_ports { spi_flas set_property -dict { PACKAGE_PIN P21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_wp_n }]; set_property -dict { PACKAGE_PIN R21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_hold_n }]; +################################################################################ +# SD card +################################################################################ + +set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_clk }] +set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sdcard_cd }] +set_property -dict { PACKAGE_PIN W20 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_cmd }] +set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[0] }] +set_property -dict { PACKAGE_PIN T21 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[1] }] +set_property -dict { PACKAGE_PIN T20 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[2] }] +set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_data[3] }] +set_property -dict { PACKAGE_PIN V20 IOSTANDARD LVCMOS33 } [get_ports { sdcard_reset }] + +# Put registers into IOBs to improve timing +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdcard_*}] + ################################################################################ # Ethernet (generated by LiteX) ################################################################################ diff --git a/fpga/top-nexys-video.vhdl b/fpga/top-nexys-video.vhdl index e99f2c5..1cf1df2 100644 --- a/fpga/top-nexys-video.vhdl +++ b/fpga/top-nexys-video.vhdl @@ -24,7 +24,8 @@ entity toplevel is SPI_FLASH_DEF_QUAD : boolean := true; LOG_LENGTH : natural := 2048; UART_IS_16550 : boolean := true; - USE_LITEETH : boolean := false + USE_LITEETH : boolean := false; + USE_LITESDCARD : boolean := false ); port( ext_clk : in std_ulogic; @@ -63,6 +64,13 @@ entity toplevel is eth_tx_ctl : out std_ulogic; eth_tx_data : out std_ulogic_vector(3 downto 0); + -- SD card + sdcard_data : inout std_ulogic_vector(3 downto 0); + sdcard_cmd : inout std_ulogic; + sdcard_clk : out std_ulogic; + sdcard_cd : in std_ulogic; + sdcard_reset : out std_ulogic; + -- DRAM wires ddram_a : out std_logic_vector(14 downto 0); ddram_ba : out std_logic_vector(2 downto 0); @@ -97,6 +105,7 @@ architecture behaviour of toplevel is signal wb_ext_is_dram_csr : std_ulogic; signal wb_ext_is_dram_init : std_ulogic; signal wb_ext_is_eth : std_ulogic; + signal wb_ext_is_sdcard : std_ulogic; -- DRAM main data wishbone connection signal wb_dram_in : wishbone_master_out; @@ -109,6 +118,16 @@ architecture behaviour of toplevel is signal ext_irq_eth : std_ulogic; signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init; + -- LiteSDCard connection + signal ext_irq_sdcard : std_ulogic := '0'; + signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init; + signal wb_sddma_out : wb_io_master_out := wb_io_master_out_init; + signal wb_sddma_in : wb_io_slave_out; + signal wb_sddma_nr : wb_io_master_out; + signal wb_sddma_ir : wb_io_slave_out; + -- for conversion from non-pipelined wishbone to pipelined + signal wb_sddma_stb_sent : std_ulogic; + -- Control/status signal core_alt_reset : std_ulogic; @@ -162,7 +181,8 @@ begin SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD, LOG_LENGTH => LOG_LENGTH, UART0_IS_16550 => UART_IS_16550, - HAS_LITEETH => USE_LITEETH + HAS_LITEETH => USE_LITEETH, + HAS_SD_CARD => USE_LITESDCARD ) port map ( -- System signals @@ -182,8 +202,9 @@ begin -- External interrupts ext_irq_eth => ext_irq_eth, + ext_irq_sdcard => ext_irq_sdcard, - -- DRAM wishbone + -- IO wishbone wb_dram_in => wb_dram_in, wb_dram_out => wb_dram_out, wb_ext_io_in => wb_ext_io_in, @@ -191,6 +212,12 @@ begin wb_ext_is_dram_csr => wb_ext_is_dram_csr, wb_ext_is_dram_init => wb_ext_is_dram_init, wb_ext_is_eth => wb_ext_is_eth, + wb_ext_is_sdcard => wb_ext_is_sdcard, + + -- DMA wishbone + wishbone_dma_in => wb_sddma_in, + wishbone_dma_out => wb_sddma_out, + alt_reset => core_alt_reset ); @@ -428,8 +455,118 @@ begin ext_irq_eth <= '0'; end generate; + -- SD card + has_sdcard : if USE_LITESDCARD generate + component litesdcard_core port ( + clk : in std_ulogic; + rst : in std_ulogic; + -- wishbone for accessing control registers + wb_ctrl_adr : in std_ulogic_vector(29 downto 0); + wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0); + wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0); + wb_ctrl_sel : in std_ulogic_vector(3 downto 0); + wb_ctrl_cyc : in std_ulogic; + wb_ctrl_stb : in std_ulogic; + wb_ctrl_ack : out std_ulogic; + wb_ctrl_we : in std_ulogic; + wb_ctrl_cti : in std_ulogic_vector(2 downto 0); + wb_ctrl_bte : in std_ulogic_vector(1 downto 0); + wb_ctrl_err : out std_ulogic; + -- wishbone for SD card core to use for DMA + wb_dma_adr : out std_ulogic_vector(29 downto 0); + wb_dma_dat_w : out std_ulogic_vector(31 downto 0); + wb_dma_dat_r : in std_ulogic_vector(31 downto 0); + wb_dma_sel : out std_ulogic_vector(3 downto 0); + wb_dma_cyc : out std_ulogic; + wb_dma_stb : out std_ulogic; + wb_dma_ack : in std_ulogic; + wb_dma_we : out std_ulogic; + wb_dma_cti : out std_ulogic_vector(2 downto 0); + wb_dma_bte : out std_ulogic_vector(1 downto 0); + wb_dma_err : in std_ulogic; + -- connections to SD card + sdcard_data : inout std_ulogic_vector(3 downto 0); + sdcard_cmd : inout std_ulogic; + sdcard_clk : out std_ulogic; + sdcard_cd : in std_ulogic; + irq : out std_ulogic + ); + end component; + + signal wb_sdcard_cyc : std_ulogic; + signal wb_sdcard_adr : std_ulogic_vector(29 downto 0); + + begin + litesdcard : litesdcard_core + port map ( + clk => system_clk, + rst => soc_rst, + wb_ctrl_adr => wb_sdcard_adr, + wb_ctrl_dat_w => wb_ext_io_in.dat, + wb_ctrl_dat_r => wb_sdcard_out.dat, + wb_ctrl_sel => wb_ext_io_in.sel, + wb_ctrl_cyc => wb_sdcard_cyc, + wb_ctrl_stb => wb_ext_io_in.stb, + wb_ctrl_ack => wb_sdcard_out.ack, + wb_ctrl_we => wb_ext_io_in.we, + wb_ctrl_cti => "000", + wb_ctrl_bte => "00", + wb_ctrl_err => open, + wb_dma_adr => wb_sddma_nr.adr, + wb_dma_dat_w => wb_sddma_nr.dat, + wb_dma_dat_r => wb_sddma_ir.dat, + wb_dma_sel => wb_sddma_nr.sel, + wb_dma_cyc => wb_sddma_nr.cyc, + wb_dma_stb => wb_sddma_nr.stb, + wb_dma_ack => wb_sddma_ir.ack, + wb_dma_we => wb_sddma_nr.we, + wb_dma_cti => open, + wb_dma_bte => open, + wb_dma_err => '0', + sdcard_data => sdcard_data, + sdcard_cmd => sdcard_cmd, + sdcard_clk => sdcard_clk, + sdcard_cd => sdcard_cd, + irq => ext_irq_sdcard + ); + + -- Gate cyc with chip select from SoC + wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard; + + wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(15 downto 2); + + wb_sdcard_out.stall <= not wb_sdcard_out.ack; + + sdcard_reset <= '0'; + + -- Convert non-pipelined DMA wishbone to pipelined by suppressing + -- non-acknowledged strobes + process(system_clk) + begin + if rising_edge(system_clk) then + wb_sddma_out <= wb_sddma_nr; + if wb_sddma_stb_sent = '1' or + (wb_sddma_out.stb = '1' and wb_sddma_in.stall = '0') then + wb_sddma_out.stb <= '0'; + end if; + if wb_sddma_nr.cyc = '0' or wb_sddma_ir.ack = '1' then + wb_sddma_stb_sent <= '0'; + elsif wb_sddma_in.stall = '0' then + wb_sddma_stb_sent <= wb_sddma_nr.stb; + end if; + wb_sddma_ir <= wb_sddma_in; + end if; + end process; + + end generate; + + no_sdcard : if not USE_LITESDCARD generate + sdcard_reset <= '1'; + end generate; + -- Mux WB response on the IO bus wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else + wb_sdcard_out when wb_ext_is_sdcard = '1' else wb_dram_ctrl_out; led4 <= system_clk_locked; diff --git a/microwatt.core b/microwatt.core index 600520e..b01983f 100644 --- a/microwatt.core +++ b/microwatt.core @@ -228,12 +228,13 @@ targets: nexys_video: default_tool: vivado - filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific] + filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific, litesdcard] parameters: - memory_size - ram_init_file - use_litedram=true - use_liteeth=true + - use_litesdcard=true - disable_flatten_core - no_bram - spi_flash_offset=10485760 @@ -241,7 +242,7 @@ targets: - uart_is_16550 - has_fpu - has_btc - generate: [litedram_nexys_video, liteeth_nexys_video] + generate: [litedram_nexys_video, liteeth_nexys_video, litesdcard_nexys_video] tools: vivado: {part : xc7a200tsbg484-1} toplevel : toplevel @@ -367,6 +368,10 @@ generate: generator: litesdcard_gen parameters: {vendor : xilinx} + litesdcard_nexys_video: + generator: litesdcard_gen + parameters: {vendor : xilinx} + litedram_nexys_video: generator: litedram_gen parameters: {board : nexys-video} -- 2.30.2