diff --git a/fpga/arty_a7.xdc b/fpga/arty_a7.xdc index df55577..3fa99bb 100644 --- a/fpga/arty_a7.xdc +++ b/fpga/arty_a7.xdc @@ -133,6 +133,22 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdpa #set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { pmod_jc_9 }]; #set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { pmod_jc_10 }]; +# connection to second Digilent PmodSD on JC +set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[3] }]; +set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_cmd }]; +set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[0] }]; +set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard2_clk }]; +set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[1] }]; +set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[2] }]; +set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sdcard2_cd }]; +#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { sdcard2_wp }]; + +# Put registers into IOBs to improve timing +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/sdpads_data_i_reg*}] +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/xilinxsdrtristateimpl*_o_reg}] +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/sdcard_clk_reg}] +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/sdpads_cmd_i_reg}] + ################################################################################ # PMOD header JD (standard, 200 ohm protection resisters) ################################################################################ diff --git a/fpga/top-arty.vhdl b/fpga/top-arty.vhdl index 54d1f90..43cea85 100644 --- a/fpga/top-arty.vhdl +++ b/fpga/top-arty.vhdl @@ -122,6 +122,12 @@ entity toplevel is sdcard_clk : out std_ulogic; sdcard_cd : in std_ulogic; + -- Second SD card + sdcard2_data : inout std_ulogic_vector(3 downto 0); + sdcard2_cmd : inout std_ulogic; + sdcard2_clk : out std_ulogic; + sdcard2_cd : in std_ulogic; + -- DRAM wires ddram_a : out std_ulogic_vector(13 downto 0); ddram_ba : out std_ulogic_vector(2 downto 0); @@ -179,11 +185,17 @@ architecture behaviour of toplevel is -- LiteSDCard connection signal ext_irq_sdcard : std_ulogic := '0'; + signal ext_irq_sdcard2 : std_ulogic := '0'; signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init; + signal wb_sdcard2_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_sddma1_nr : wb_io_master_out; + signal wb_sddma2_nr : wb_io_master_out; signal wb_sddma_ir : wb_io_slave_out; + signal wb_sddma1_ack : std_ulogic; + signal wb_sddma2_ack : std_ulogic; -- for conversion from non-pipelined wishbone to pipelined signal wb_sddma_stb_sent : std_ulogic; @@ -261,6 +273,7 @@ begin UART0_IS_16550 => UART_IS_16550, HAS_UART1 => HAS_UART1, HAS_SD_CARD => USE_LITESDCARD, + HAS_SD_CARD2 => USE_LITESDCARD, HAS_GPIO => HAS_GPIO, NGPIO => NGPIO ) @@ -295,6 +308,7 @@ begin -- External interrupts ext_irq_eth => ext_irq_eth, ext_irq_sdcard => ext_irq_sdcard, + ext_irq_sdcard2 => ext_irq_sdcard2, -- DRAM wishbone wb_dram_in => wb_dram_in, @@ -623,7 +637,7 @@ begin ext_irq_eth <= '0'; end generate; - -- SD card pmod + -- SD card pmod, two interfaces has_sdcard : if USE_LITESDCARD generate component litesdcard_core port ( clk : in std_ulogic; @@ -662,7 +676,10 @@ begin end component; signal wb_sdcard_cyc : std_ulogic; + signal wb_sdcard2_cyc : std_ulogic; signal wb_sdcard_adr : std_ulogic_vector(29 downto 0); + signal dma_msel : std_ulogic; + signal other_cyc : std_ulogic; begin litesdcard : litesdcard_core @@ -680,14 +697,14 @@ begin 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_adr => wb_sddma1_nr.adr, + wb_dma_dat_w => wb_sddma1_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_sel => wb_sddma1_nr.sel, + wb_dma_cyc => wb_sddma1_nr.cyc, + wb_dma_stb => wb_sddma1_nr.stb, + wb_dma_ack => wb_sddma1_ack, + wb_dma_we => wb_sddma1_nr.we, wb_dma_cti => open, wb_dma_bte => open, wb_dma_err => '0', @@ -698,13 +715,55 @@ begin irq => ext_irq_sdcard ); - -- Gate cyc with chip select from SoC - wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard; + litesdcard2 : litesdcard_core + port map ( + clk => system_clk, + rst => periph_rst, + wb_ctrl_adr => wb_sdcard_adr, + wb_ctrl_dat_w => wb_ext_io_in.dat, + wb_ctrl_dat_r => wb_sdcard2_out.dat, + wb_ctrl_sel => wb_ext_io_in.sel, + wb_ctrl_cyc => wb_sdcard2_cyc, + wb_ctrl_stb => wb_ext_io_in.stb, + wb_ctrl_ack => wb_sdcard2_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_sddma2_nr.adr, + wb_dma_dat_w => wb_sddma2_nr.dat, + wb_dma_dat_r => wb_sddma_ir.dat, + wb_dma_sel => wb_sddma2_nr.sel, + wb_dma_cyc => wb_sddma2_nr.cyc, + wb_dma_stb => wb_sddma2_nr.stb, + wb_dma_ack => wb_sddma2_ack, + wb_dma_we => wb_sddma2_nr.we, + wb_dma_cti => open, + wb_dma_bte => open, + wb_dma_err => '0', + sdcard_data => sdcard2_data, + sdcard_cmd => sdcard2_cmd, + sdcard_clk => sdcard2_clk, + sdcard_cd => sdcard2_cd, + irq => ext_irq_sdcard2 + ); - wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0); + -- Gate cyc with chip selects from SoC + -- Select first or second interface based on real address bit 15 + wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard and not wb_ext_io_in.adr(13); + wb_sdcard2_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard and wb_ext_io_in.adr(13); - wb_sdcard_out.stall <= not wb_sdcard_out.ack; + wb_sdcard_adr <= 17x"0" & wb_ext_io_in.adr(12 downto 0); + wb_sdcard_out.stall <= not wb_sdcard_out.ack; + wb_sdcard2_out.stall <= not wb_sdcard2_out.ack; + + -- Simple arbiter to multiplex the two DMA wishbones + wb_sddma_nr <= wb_sddma1_nr when dma_msel = '0' else wb_sddma2_nr; + wb_sddma1_ack <= wb_sddma_ir.ack and not dma_msel; + wb_sddma2_ack <= wb_sddma_ir.ack and dma_msel; + other_cyc <= wb_sddma2_nr.cyc when dma_msel = '0' else wb_sddma1_nr.cyc; + -- Convert non-pipelined DMA wishbone to pipelined by suppressing -- non-acknowledged strobes process(system_clk) @@ -721,6 +780,13 @@ begin wb_sddma_stb_sent <= wb_sddma_nr.stb; end if; wb_sddma_ir <= wb_sddma_in; + + -- Decide which wishbone to use next cycle + if periph_rst = '1' then + dma_msel <= '0'; + elsif wb_sddma_nr.cyc = '0' and other_cyc = '1' then + dma_msel <= not dma_msel; + end if; end if; end process; @@ -728,7 +794,8 @@ begin -- 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_sdcard_out when wb_ext_is_sdcard = '1' and wb_ext_io_in.adr(13) = '0' else + wb_sdcard2_out when wb_ext_is_sdcard = '1' and wb_ext_io_in.adr(13) = '1' else wb_dram_ctrl_out; leds_pwm : process(system_clk) diff --git a/include/microwatt_soc.h b/include/microwatt_soc.h index 6e367b1..6203535 100644 --- a/include/microwatt_soc.h +++ b/include/microwatt_soc.h @@ -19,6 +19,7 @@ #define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */ #define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */ #define LSDC_CSR_BASE 0xc8040000 /* LiteSDCard MMIO space */ +#define LSDC2_CSR_BASE 0xc8048000 /* 2nd LiteSDCard MMIO space */ #define SPI_FLASH_BASE 0xf0000000 /* SPI Flash memory map */ #define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */ @@ -30,6 +31,7 @@ #define IRQ_UART1 2 #define IRQ_SDCARD 3 #define IRQ_GPIO 4 +#define IRQ_SDCARD2 5 /* * Register definitions for the syscon registers @@ -46,6 +48,7 @@ #define SYS_REG_INFO_HAS_UART1 (1ull << 6) #define SYS_REG_INFO_HAS_ARTB (1ull << 7) #define SYS_REG_INFO_HAS_LITESDCARD (1ull << 8) +#define SYS_REG_INFO_HAS_LITESDCARD2 (1ull << 9) #define SYS_REG_BRAMINFO 0x10 #define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull #define SYS_REG_DRAMINFO 0x18 diff --git a/soc.vhdl b/soc.vhdl index 3daeb73..fc30014 100644 --- a/soc.vhdl +++ b/soc.vhdl @@ -50,6 +50,7 @@ use work.wishbone_types.all; -- 2 : UART1 -- 3 : SD card -- 4 : GPIO +-- 5 : SD card 2 -- Resets: -- The soc can be reset externally by its parent top- entity (via rst port), @@ -93,6 +94,7 @@ entity soc is DCACHE_TLB_SET_SIZE : natural := 64; DCACHE_TLB_NUM_WAYS : natural := 2; HAS_SD_CARD : boolean := false; + HAS_SD_CARD2 : boolean := false; HAS_GPIO : boolean := false; NGPIO : natural := 32 ); @@ -122,6 +124,7 @@ entity soc is -- External interrupts ext_irq_eth : in std_ulogic := '0'; ext_irq_sdcard : in std_ulogic := '0'; + ext_irq_sdcard2 : in std_ulogic := '0'; -- UART0 signals: uart0_txd : out std_ulogic; @@ -822,6 +825,7 @@ begin SPI_FLASH_OFFSET => SPI_FLASH_OFFSET, HAS_LITEETH => HAS_LITEETH, HAS_SD_CARD => HAS_SD_CARD, + HAS_SD_CARD2 => HAS_SD_CARD2, UART0_IS_16550 => UART0_IS_16550, HAS_UART1 => HAS_UART1 ) @@ -1031,6 +1035,7 @@ begin int_level_in(2) <= uart1_irq; int_level_in(3) <= ext_irq_sdcard; int_level_in(4) <= gpio_intr; + int_level_in(5) <= ext_irq_sdcard2; end process; -- BRAM Memory slave diff --git a/syscon.vhdl b/syscon.vhdl index ad9ba2c..bdeabd2 100644 --- a/syscon.vhdl +++ b/syscon.vhdl @@ -21,6 +21,7 @@ entity syscon is SPI_FLASH_OFFSET : integer; HAS_LITEETH : boolean; HAS_SD_CARD : boolean; + HAS_SD_CARD2 : boolean; UART0_IS_16550 : boolean; HAS_UART1 : boolean ); @@ -75,6 +76,7 @@ architecture behaviour of syscon is constant SYS_REG_INFO_HAS_URT1 : integer := 6; -- Has second UART constant SYS_REG_INFO_HAS_ARTB : integer := 7; -- Has architected TB frequency constant SYS_REG_INFO_HAS_SDCARD : integer := 8; -- Has LiteSDCard SD-card interface + constant SYS_REG_INFO_HAS_SDCARD2 : integer := 9; -- Has 2nd LiteSDCard SD-card interface -- BRAMINFO contains the BRAM size in the bottom 52 bits -- DRAMINFO contains the DRAM size if any in the bottom 52 bits @@ -129,6 +131,7 @@ architecture behaviour of syscon is signal info_has_spif : std_ulogic; signal info_has_leth : std_ulogic; signal info_has_lsdc : std_ulogic; + signal info_has_lsd2 : std_ulogic; signal info_has_urt1 : std_ulogic; signal info_clk : std_ulogic_vector(39 downto 0); signal info_fl_off : std_ulogic_vector(31 downto 0); @@ -155,6 +158,7 @@ begin info_has_spif <= '1' when HAS_SPI_FLASH else '0'; info_has_leth <= '1' when HAS_LITEETH else '0'; info_has_lsdc <= '1' when HAS_SD_CARD else '0'; + info_has_lsd2 <= '1' when HAS_SD_CARD2 else '0'; info_has_urt1 <= '1' when HAS_UART1 else '0'; info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40)); reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart, @@ -163,6 +167,7 @@ begin SYS_REG_INFO_HAS_SPIF => info_has_spif, SYS_REG_INFO_HAS_LETH => info_has_leth, SYS_REG_INFO_HAS_SDCARD => info_has_lsdc, + SYS_REG_INFO_HAS_SDCARD2 => info_has_lsd2, SYS_REG_INFO_HAS_LSYS => '1', SYS_REG_INFO_HAS_URT1 => info_has_urt1, others => '0');