arty a7: Add a second SD card interface on pmod JC

This adds a second SD card interface.  The main complexity is in
providing a wishbone switch/arbiter to multiplex the two DMA
wishbones from the two interfaces to a single wishbone going to
the soc module.  There is a new syscon info reg bit to indicate the
presence of the second litesdcard.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/461/head
Paul Mackerras 1 month ago
parent 6366fbb5a7
commit 4f06a01731

@ -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 T13 IOSTANDARD LVCMOS33 } [get_ports { pmod_jc_9 }];
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { pmod_jc_10 }]; #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) # PMOD header JD (standard, 200 ohm protection resisters)
################################################################################ ################################################################################

@ -122,6 +122,12 @@ entity toplevel is
sdcard_clk : out std_ulogic; sdcard_clk : out std_ulogic;
sdcard_cd : in 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 -- DRAM wires
ddram_a : out std_ulogic_vector(13 downto 0); ddram_a : out std_ulogic_vector(13 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0); ddram_ba : out std_ulogic_vector(2 downto 0);
@ -179,11 +185,17 @@ architecture behaviour of toplevel is


-- LiteSDCard connection -- LiteSDCard connection
signal ext_irq_sdcard : std_ulogic := '0'; 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_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_out : wb_io_master_out := wb_io_master_out_init;
signal wb_sddma_in : wb_io_slave_out; signal wb_sddma_in : wb_io_slave_out;
signal wb_sddma_nr : wb_io_master_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_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 -- for conversion from non-pipelined wishbone to pipelined
signal wb_sddma_stb_sent : std_ulogic; signal wb_sddma_stb_sent : std_ulogic;


@ -261,6 +273,7 @@ begin
UART0_IS_16550 => UART_IS_16550, UART0_IS_16550 => UART_IS_16550,
HAS_UART1 => HAS_UART1, HAS_UART1 => HAS_UART1,
HAS_SD_CARD => USE_LITESDCARD, HAS_SD_CARD => USE_LITESDCARD,
HAS_SD_CARD2 => USE_LITESDCARD,
HAS_GPIO => HAS_GPIO, HAS_GPIO => HAS_GPIO,
NGPIO => NGPIO NGPIO => NGPIO
) )
@ -295,6 +308,7 @@ begin
-- External interrupts -- External interrupts
ext_irq_eth => ext_irq_eth, ext_irq_eth => ext_irq_eth,
ext_irq_sdcard => ext_irq_sdcard, ext_irq_sdcard => ext_irq_sdcard,
ext_irq_sdcard2 => ext_irq_sdcard2,


-- DRAM wishbone -- DRAM wishbone
wb_dram_in => wb_dram_in, wb_dram_in => wb_dram_in,
@ -623,7 +637,7 @@ begin
ext_irq_eth <= '0'; ext_irq_eth <= '0';
end generate; end generate;


-- SD card pmod -- SD card pmod, two interfaces
has_sdcard : if USE_LITESDCARD generate has_sdcard : if USE_LITESDCARD generate
component litesdcard_core port ( component litesdcard_core port (
clk : in std_ulogic; clk : in std_ulogic;
@ -662,7 +676,10 @@ begin
end component; end component;


signal wb_sdcard_cyc : std_ulogic; signal wb_sdcard_cyc : std_ulogic;
signal wb_sdcard2_cyc : std_ulogic;
signal wb_sdcard_adr : std_ulogic_vector(29 downto 0); signal wb_sdcard_adr : std_ulogic_vector(29 downto 0);
signal dma_msel : std_ulogic;
signal other_cyc : std_ulogic;


begin begin
litesdcard : litesdcard_core litesdcard : litesdcard_core
@ -680,14 +697,14 @@ begin
wb_ctrl_cti => "000", wb_ctrl_cti => "000",
wb_ctrl_bte => "00", wb_ctrl_bte => "00",
wb_ctrl_err => open, wb_ctrl_err => open,
wb_dma_adr => wb_sddma_nr.adr, wb_dma_adr => wb_sddma1_nr.adr,
wb_dma_dat_w => wb_sddma_nr.dat, wb_dma_dat_w => wb_sddma1_nr.dat,
wb_dma_dat_r => wb_sddma_ir.dat, wb_dma_dat_r => wb_sddma_ir.dat,
wb_dma_sel => wb_sddma_nr.sel, wb_dma_sel => wb_sddma1_nr.sel,
wb_dma_cyc => wb_sddma_nr.cyc, wb_dma_cyc => wb_sddma1_nr.cyc,
wb_dma_stb => wb_sddma_nr.stb, wb_dma_stb => wb_sddma1_nr.stb,
wb_dma_ack => wb_sddma_ir.ack, wb_dma_ack => wb_sddma1_ack,
wb_dma_we => wb_sddma_nr.we, wb_dma_we => wb_sddma1_nr.we,
wb_dma_cti => open, wb_dma_cti => open,
wb_dma_bte => open, wb_dma_bte => open,
wb_dma_err => '0', wb_dma_err => '0',
@ -698,12 +715,54 @@ begin
irq => ext_irq_sdcard irq => ext_irq_sdcard
); );


-- Gate cyc with chip select from SoC litesdcard2 : litesdcard_core
wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard; 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
);

-- 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_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0); wb_sdcard_adr <= 17x"0" & wb_ext_io_in.adr(12 downto 0);


wb_sdcard_out.stall <= not wb_sdcard_out.ack; 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 -- Convert non-pipelined DMA wishbone to pipelined by suppressing
-- non-acknowledged strobes -- non-acknowledged strobes
@ -721,6 +780,13 @@ begin
wb_sddma_stb_sent <= wb_sddma_nr.stb; wb_sddma_stb_sent <= wb_sddma_nr.stb;
end if; end if;
wb_sddma_ir <= wb_sddma_in; 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 if;
end process; end process;


@ -728,7 +794,8 @@ begin


-- Mux WB response on the IO bus -- Mux WB response on the IO bus
wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else 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; wb_dram_ctrl_out;


leds_pwm : process(system_clk) leds_pwm : process(system_clk)

@ -19,6 +19,7 @@
#define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */ #define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */
#define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */ #define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */
#define LSDC_CSR_BASE 0xc8040000 /* LiteSDCard 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 SPI_FLASH_BASE 0xf0000000 /* SPI Flash memory map */
#define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */ #define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */


@ -30,6 +31,7 @@
#define IRQ_UART1 2 #define IRQ_UART1 2
#define IRQ_SDCARD 3 #define IRQ_SDCARD 3
#define IRQ_GPIO 4 #define IRQ_GPIO 4
#define IRQ_SDCARD2 5


/* /*
* Register definitions for the syscon registers * Register definitions for the syscon registers
@ -46,6 +48,7 @@
#define SYS_REG_INFO_HAS_UART1 (1ull << 6) #define SYS_REG_INFO_HAS_UART1 (1ull << 6)
#define SYS_REG_INFO_HAS_ARTB (1ull << 7) #define SYS_REG_INFO_HAS_ARTB (1ull << 7)
#define SYS_REG_INFO_HAS_LITESDCARD (1ull << 8) #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 0x10
#define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull #define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull
#define SYS_REG_DRAMINFO 0x18 #define SYS_REG_DRAMINFO 0x18

@ -50,6 +50,7 @@ use work.wishbone_types.all;
-- 2 : UART1 -- 2 : UART1
-- 3 : SD card -- 3 : SD card
-- 4 : GPIO -- 4 : GPIO
-- 5 : SD card 2


-- Resets: -- Resets:
-- The soc can be reset externally by its parent top- entity (via rst port), -- 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_SET_SIZE : natural := 64;
DCACHE_TLB_NUM_WAYS : natural := 2; DCACHE_TLB_NUM_WAYS : natural := 2;
HAS_SD_CARD : boolean := false; HAS_SD_CARD : boolean := false;
HAS_SD_CARD2 : boolean := false;
HAS_GPIO : boolean := false; HAS_GPIO : boolean := false;
NGPIO : natural := 32 NGPIO : natural := 32
); );
@ -122,6 +124,7 @@ entity soc is
-- External interrupts -- External interrupts
ext_irq_eth : in std_ulogic := '0'; ext_irq_eth : in std_ulogic := '0';
ext_irq_sdcard : in std_ulogic := '0'; ext_irq_sdcard : in std_ulogic := '0';
ext_irq_sdcard2 : in std_ulogic := '0';


-- UART0 signals: -- UART0 signals:
uart0_txd : out std_ulogic; uart0_txd : out std_ulogic;
@ -822,6 +825,7 @@ begin
SPI_FLASH_OFFSET => SPI_FLASH_OFFSET, SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
HAS_LITEETH => HAS_LITEETH, HAS_LITEETH => HAS_LITEETH,
HAS_SD_CARD => HAS_SD_CARD, HAS_SD_CARD => HAS_SD_CARD,
HAS_SD_CARD2 => HAS_SD_CARD2,
UART0_IS_16550 => UART0_IS_16550, UART0_IS_16550 => UART0_IS_16550,
HAS_UART1 => HAS_UART1 HAS_UART1 => HAS_UART1
) )
@ -1031,6 +1035,7 @@ begin
int_level_in(2) <= uart1_irq; int_level_in(2) <= uart1_irq;
int_level_in(3) <= ext_irq_sdcard; int_level_in(3) <= ext_irq_sdcard;
int_level_in(4) <= gpio_intr; int_level_in(4) <= gpio_intr;
int_level_in(5) <= ext_irq_sdcard2;
end process; end process;


-- BRAM Memory slave -- BRAM Memory slave

@ -21,6 +21,7 @@ entity syscon is
SPI_FLASH_OFFSET : integer; SPI_FLASH_OFFSET : integer;
HAS_LITEETH : boolean; HAS_LITEETH : boolean;
HAS_SD_CARD : boolean; HAS_SD_CARD : boolean;
HAS_SD_CARD2 : boolean;
UART0_IS_16550 : boolean; UART0_IS_16550 : boolean;
HAS_UART1 : 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_URT1 : integer := 6; -- Has second UART
constant SYS_REG_INFO_HAS_ARTB : integer := 7; -- Has architected TB frequency 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_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 -- BRAMINFO contains the BRAM size in the bottom 52 bits
-- DRAMINFO contains the DRAM size if any 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_spif : std_ulogic;
signal info_has_leth : std_ulogic; signal info_has_leth : std_ulogic;
signal info_has_lsdc : std_ulogic; signal info_has_lsdc : std_ulogic;
signal info_has_lsd2 : std_ulogic;
signal info_has_urt1 : std_ulogic; signal info_has_urt1 : std_ulogic;
signal info_clk : std_ulogic_vector(39 downto 0); signal info_clk : std_ulogic_vector(39 downto 0);
signal info_fl_off : std_ulogic_vector(31 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_spif <= '1' when HAS_SPI_FLASH else '0';
info_has_leth <= '1' when HAS_LITEETH else '0'; info_has_leth <= '1' when HAS_LITEETH else '0';
info_has_lsdc <= '1' when HAS_SD_CARD 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_has_urt1 <= '1' when HAS_UART1 else '0';
info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40)); info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart, 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_SPIF => info_has_spif,
SYS_REG_INFO_HAS_LETH => info_has_leth, SYS_REG_INFO_HAS_LETH => info_has_leth,
SYS_REG_INFO_HAS_SDCARD => info_has_lsdc, 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_LSYS => '1',
SYS_REG_INFO_HAS_URT1 => info_has_urt1, SYS_REG_INFO_HAS_URT1 => info_has_urt1,
others => '0'); others => '0');

Loading…
Cancel
Save