From 9b184ff56910b38f125b2b55428c7ddf93672d44 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 27 Oct 2021 14:58:34 +1100 Subject: [PATCH] antmicro-artix-dc-scm: Add DRAM support This uses the exact same gateware as the nexys video, since the DRAM connection is identical to the nexys video down to the pin assignments on the FPGA. The only minor difference is that the DRAM chip on the dc-scm is a MT41K256M16TW vs. a ...HA part on the nexys video. Signed-off-by: Paul Mackerras [joel: rebase and tweaks] Signed-off-by: Joel Stanley --- fpga/antmicro_artix_dc_scm.xdc | 261 ++++++++++++++++++++++++++++ fpga/top-antmicro-artix-dc-scm.vhdl | 196 +++++++++++++++++---- microwatt.core | 6 +- 3 files changed, 426 insertions(+), 37 deletions(-) diff --git a/fpga/antmicro_artix_dc_scm.xdc b/fpga/antmicro_artix_dc_scm.xdc index 7b17439..b487eb0 100644 --- a/fpga/antmicro_artix_dc_scm.xdc +++ b/fpga/antmicro_artix_dc_scm.xdc @@ -12,12 +12,273 @@ set_property -dict { PACKAGE_PIN U20 IOSTANDARD LVCMOS33 } [get_ports { d12_led set_property -dict { PACKAGE_PIN W20 IOSTANDARD LVCMOS33 } [get_ports { d13_led }]; +################################################################################ +# DRAM (generated by LiteX) +################################################################################ + +# ddram:0.a +set_property LOC M2 [get_ports {ddram_a[0]}] +set_property SLEW FAST [get_ports {ddram_a[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[0]}] + +# ddram:0.a +set_property LOC M5 [get_ports {ddram_a[1]}] +set_property SLEW FAST [get_ports {ddram_a[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[1]}] + +# ddram:0.a +set_property LOC M3 [get_ports {ddram_a[2]}] +set_property SLEW FAST [get_ports {ddram_a[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[2]}] + +# ddram:0.a +set_property LOC M1 [get_ports {ddram_a[3]}] +set_property SLEW FAST [get_ports {ddram_a[3]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[3]}] + +# ddram:0.a +set_property LOC L6 [get_ports {ddram_a[4]}] +set_property SLEW FAST [get_ports {ddram_a[4]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[4]}] + +# ddram:0.a +set_property LOC P1 [get_ports {ddram_a[5]}] +set_property SLEW FAST [get_ports {ddram_a[5]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[5]}] + +# ddram:0.a +set_property LOC N3 [get_ports {ddram_a[6]}] +set_property SLEW FAST [get_ports {ddram_a[6]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[6]}] + +# ddram:0.a +set_property LOC N2 [get_ports {ddram_a[7]}] +set_property SLEW FAST [get_ports {ddram_a[7]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[7]}] + +# ddram:0.a +set_property LOC M6 [get_ports {ddram_a[8]}] +set_property SLEW FAST [get_ports {ddram_a[8]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[8]}] + +# ddram:0.a +set_property LOC R1 [get_ports {ddram_a[9]}] +set_property SLEW FAST [get_ports {ddram_a[9]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[9]}] + +# ddram:0.a +set_property LOC L5 [get_ports {ddram_a[10]}] +set_property SLEW FAST [get_ports {ddram_a[10]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[10]}] + +# ddram:0.a +set_property LOC N5 [get_ports {ddram_a[11]}] +set_property SLEW FAST [get_ports {ddram_a[11]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[11]}] + +# ddram:0.a +set_property LOC N4 [get_ports {ddram_a[12]}] +set_property SLEW FAST [get_ports {ddram_a[12]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[12]}] + +# ddram:0.a +set_property LOC P2 [get_ports {ddram_a[13]}] +set_property SLEW FAST [get_ports {ddram_a[13]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[13]}] + +# ddram:0.a +set_property LOC P6 [get_ports {ddram_a[14]}] +set_property SLEW FAST [get_ports {ddram_a[14]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_a[14]}] + +# ddram:0.ba +set_property LOC L3 [get_ports {ddram_ba[0]}] +set_property SLEW FAST [get_ports {ddram_ba[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_ba[0]}] + +# ddram:0.ba +set_property LOC K6 [get_ports {ddram_ba[1]}] +set_property SLEW FAST [get_ports {ddram_ba[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_ba[1]}] + +# ddram:0.ba +set_property LOC L4 [get_ports {ddram_ba[2]}] +set_property SLEW FAST [get_ports {ddram_ba[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_ba[2]}] + +# ddram:0.ras_n +set_property LOC J4 [get_ports {ddram_ras_n}] +set_property SLEW FAST [get_ports {ddram_ras_n}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_ras_n}] + +# ddram:0.cas_n +set_property LOC K3 [get_ports {ddram_cas_n}] +set_property SLEW FAST [get_ports {ddram_cas_n}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_cas_n}] + +# ddram:0.we_n +set_property LOC L1 [get_ports {ddram_we_n}] +set_property SLEW FAST [get_ports {ddram_we_n}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_we_n}] + +# ddram:0.dm +set_property LOC G3 [get_ports {ddram_dm[0]}] +set_property SLEW FAST [get_ports {ddram_dm[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dm[0]}] + +# ddram:0.dm +set_property LOC F1 [get_ports {ddram_dm[1]}] +set_property SLEW FAST [get_ports {ddram_dm[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dm[1]}] + +# ddram:0.dq +set_property LOC G2 [get_ports {ddram_dq[0]}] +set_property SLEW FAST [get_ports {ddram_dq[0]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[0]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[0]}] + +# ddram:0.dq +set_property LOC H4 [get_ports {ddram_dq[1]}] +set_property SLEW FAST [get_ports {ddram_dq[1]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[1]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[1]}] + +# ddram:0.dq +set_property LOC H5 [get_ports {ddram_dq[2]}] +set_property SLEW FAST [get_ports {ddram_dq[2]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[2]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[2]}] + +# ddram:0.dq +set_property LOC J1 [get_ports {ddram_dq[3]}] +set_property SLEW FAST [get_ports {ddram_dq[3]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[3]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[3]}] + +# ddram:0.dq +set_property LOC K1 [get_ports {ddram_dq[4]}] +set_property SLEW FAST [get_ports {ddram_dq[4]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[4]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[4]}] + +# ddram:0.dq +set_property LOC H3 [get_ports {ddram_dq[5]}] +set_property SLEW FAST [get_ports {ddram_dq[5]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[5]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[5]}] + +# ddram:0.dq +set_property LOC H2 [get_ports {ddram_dq[6]}] +set_property SLEW FAST [get_ports {ddram_dq[6]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[6]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[6]}] + +# ddram:0.dq +set_property LOC J5 [get_ports {ddram_dq[7]}] +set_property SLEW FAST [get_ports {ddram_dq[7]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[7]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[7]}] + +# ddram:0.dq +set_property LOC E3 [get_ports {ddram_dq[8]}] +set_property SLEW FAST [get_ports {ddram_dq[8]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[8]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[8]}] + +# ddram:0.dq +set_property LOC B2 [get_ports {ddram_dq[9]}] +set_property SLEW FAST [get_ports {ddram_dq[9]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[9]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[9]}] + +# ddram:0.dq +set_property LOC F3 [get_ports {ddram_dq[10]}] +set_property SLEW FAST [get_ports {ddram_dq[10]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[10]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[10]}] + +# ddram:0.dq +set_property LOC D2 [get_ports {ddram_dq[11]}] +set_property SLEW FAST [get_ports {ddram_dq[11]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[11]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[11]}] + +# ddram:0.dq +set_property LOC C2 [get_ports {ddram_dq[12]}] +set_property SLEW FAST [get_ports {ddram_dq[12]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[12]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[12]}] + +# ddram:0.dq +set_property LOC A1 [get_ports {ddram_dq[13]}] +set_property SLEW FAST [get_ports {ddram_dq[13]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[13]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[13]}] + +# ddram:0.dq +set_property LOC E2 [get_ports {ddram_dq[14]}] +set_property SLEW FAST [get_ports {ddram_dq[14]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[14]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[14]}] + +# ddram:0.dq +set_property LOC B1 [get_ports {ddram_dq[15]}] +set_property SLEW FAST [get_ports {ddram_dq[15]}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_dq[15]}] +set_property IN_TERM UNTUNED_SPLIT_50 [get_ports {ddram_dq[15]}] + +# ddram:0.dqs_p +set_property LOC K2 [get_ports {ddram_dqs_p[0]}] +set_property SLEW FAST [get_ports {ddram_dqs_p[0]}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddram_dqs_p[0]}] + +# ddram:0.dqs_p +set_property LOC E1 [get_ports {ddram_dqs_p[1]}] +set_property SLEW FAST [get_ports {ddram_dqs_p[1]}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddram_dqs_p[1]}] + +# ddram:0.dqs_n +set_property LOC J2 [get_ports {ddram_dqs_n[0]}] +set_property SLEW FAST [get_ports {ddram_dqs_n[0]}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddram_dqs_n[0]}] + +# ddram:0.dqs_n +set_property LOC D1 [get_ports {ddram_dqs_n[1]}] +set_property SLEW FAST [get_ports {ddram_dqs_n[1]}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddram_dqs_n[1]}] + +# ddram:0.clk_p +set_property LOC P5 [get_ports {ddram_clk_p}] +set_property SLEW FAST [get_ports {ddram_clk_p}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddram_clk_p}] + +# ddram:0.clk_n +set_property LOC P4 [get_ports {ddram_clk_n}] +set_property SLEW FAST [get_ports {ddram_clk_n}] +set_property IOSTANDARD DIFF_SSTL15 [get_ports {ddram_clk_n}] + +# ddram:0.cke +set_property LOC J6 [get_ports {ddram_cke}] +set_property SLEW FAST [get_ports {ddram_cke}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_cke}] + +# ddram:0.odt +set_property LOC K4 [get_ports {ddram_odt}] +set_property SLEW FAST [get_ports {ddram_odt}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_odt}] + +# ddram:0.reset_n +set_property LOC G1 [get_ports {ddram_reset_n}] +set_property SLEW FAST [get_ports {ddram_reset_n}] +set_property IOSTANDARD SSTL15 [get_ports {ddram_reset_n}] + ################################################################################ # Design constraints and bitsteam attributes ################################################################################ #Internal VREF set_property INTERNAL_VREF 0.675 [get_iobanks 34] +set_property INTERNAL_VREF 0.675 [get_iobanks 35] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property CFGBVS VCCO [current_design] diff --git a/fpga/top-antmicro-artix-dc-scm.vhdl b/fpga/top-antmicro-artix-dc-scm.vhdl index 8f6d56c..09da05c 100644 --- a/fpga/top-antmicro-artix-dc-scm.vhdl +++ b/fpga/top-antmicro-artix-dc-scm.vhdl @@ -40,8 +40,23 @@ entity toplevel is -- UART0 signals: uart_main_tx : out std_ulogic; - uart_main_rx : in std_ulogic + uart_main_rx : in std_ulogic; + -- DRAM wires + ddram_a : out std_logic_vector(14 downto 0); + ddram_ba : out std_logic_vector(2 downto 0); + ddram_ras_n : out std_logic; + ddram_cas_n : out std_logic; + ddram_we_n : out std_logic; + ddram_dm : out std_logic_vector(1 downto 0); + ddram_dq : inout std_logic_vector(15 downto 0); + ddram_dqs_p : inout std_logic_vector(1 downto 0); + ddram_dqs_n : inout std_logic_vector(1 downto 0); + ddram_clk_p : out std_logic; + ddram_clk_n : out std_logic; + ddram_cke : out std_logic; + ddram_odt : out std_logic; + ddram_reset_n : out std_logic ); end entity toplevel; @@ -60,6 +75,8 @@ architecture behaviour of toplevel is -- External IOs from the SoC signal wb_ext_io_in : wb_io_master_out; signal wb_ext_io_out : wb_io_slave_out; + signal wb_ext_is_dram_csr : std_ulogic; + signal wb_ext_is_dram_init : std_ulogic; -- DRAM main data wishbone connection signal wb_dram_in : wishbone_master_out; @@ -100,6 +117,10 @@ architecture behaviour of toplevel is signal spi_sdat_oe : std_ulogic_vector(3 downto 0); signal spi_sdat_i : std_ulogic_vector(3 downto 0); + -- ddram clock signals as vectors + signal ddram_clk_p_vec : std_logic_vector(0 downto 0); + signal ddram_clk_n_vec : std_logic_vector(0 downto 0); + -- GPIO signal gpio_in : std_ulogic_vector(NGPIO - 1 downto 0); signal gpio_out : std_ulogic_vector(NGPIO - 1 downto 0); @@ -189,8 +210,8 @@ begin -- IO wishbone wb_ext_io_in => wb_ext_io_in, wb_ext_io_out => wb_ext_io_out, --- wb_ext_is_dram_csr => , --- wb_ext_is_dram_init => , + 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_sdcard => , @@ -201,34 +222,143 @@ begin alt_reset => core_alt_reset ); - reset_controller: entity work.soc_reset - generic map( - RESET_LOW => RESET_LOW - ) - port map( - ext_clk => ext_clk, - pll_clk => system_clk, - pll_locked_in => system_clk_locked, - ext_rst_in => ext_rst_n, - pll_rst_out => pll_rst, - rst_out => soc_rst - ); - - clkgen: entity work.clock_generator - generic map( - CLK_INPUT_HZ => 100000000, - CLK_OUTPUT_HZ => CLK_FREQUENCY - ) - port map( - ext_clk => ext_clk, - pll_rst_in => pll_rst, - pll_clk_out => system_clk, - pll_locked_out => system_clk_locked - ); - - wb_ext_io_out.dat <= (others => '0'); - wb_ext_io_out.ack <= '0'; - wb_ext_io_out.stall <= '0'; + nodram: if not USE_LITEDRAM generate + signal ddram_clk_dummy : std_ulogic; + begin + reset_controller: entity work.soc_reset + generic map( + RESET_LOW => RESET_LOW + ) + port map( + ext_clk => ext_clk, + pll_clk => system_clk, + pll_locked_in => system_clk_locked, + ext_rst_in => ext_rst_n, + pll_rst_out => pll_rst, + rst_out => soc_rst + ); + + clkgen: entity work.clock_generator + generic map( + CLK_INPUT_HZ => 100000000, + CLK_OUTPUT_HZ => CLK_FREQUENCY + ) + port map( + ext_clk => ext_clk, + pll_rst_in => pll_rst, + pll_clk_out => system_clk, + pll_locked_out => system_clk_locked + ); + + core_alt_reset <= '0'; + + d11_led <= '0'; + d12_led <= soc_rst; + d13_led <= system_clk; + + -- Vivado barfs on those differential signals if left + -- unconnected. So instanciate a diff. buffer and feed + -- it a constant '0'. + dummy_dram_clk: OBUFDS + port map ( + O => ddram_clk_p, + OB => ddram_clk_n, + I => ddram_clk_dummy + ); + ddram_clk_dummy <= '0'; + + end generate; + + has_dram: if USE_LITEDRAM generate + signal dram_init_done : std_ulogic; + signal dram_init_error : std_ulogic; + signal dram_sys_rst : std_ulogic; + begin + + -- Eventually dig out the frequency from the generator + -- but for now, assert it's 100Mhz + assert CLK_FREQUENCY = 100000000; + + reset_controller: entity work.soc_reset + generic map( + RESET_LOW => RESET_LOW, + PLL_RESET_BITS => 18, + SOC_RESET_BITS => 1 + ) + port map( + ext_clk => ext_clk, + pll_clk => system_clk, + pll_locked_in => '1', + ext_rst_in => ext_rst_n, + pll_rst_out => pll_rst, + rst_out => open + ); + + -- Generate SoC reset + soc_rst_gen: process(system_clk) + begin + if ext_rst_n = '0' then + soc_rst <= '1'; + elsif rising_edge(system_clk) then + soc_rst <= dram_sys_rst or not system_clk_locked; + end if; + end process; + + ddram_clk_p_vec <= (others => ddram_clk_p); + ddram_clk_n_vec <= (others => ddram_clk_n); + + dram: entity work.litedram_wrapper + generic map( + DRAM_ABITS => 25, + DRAM_ALINES => 15, + DRAM_DLINES => 16, + DRAM_CKLINES => 1, + DRAM_PORT_WIDTH => 128, + PAYLOAD_FILE => RAM_INIT_FILE, + PAYLOAD_SIZE => PAYLOAD_SIZE + ) + port map( + clk_in => ext_clk, + rst => pll_rst, + system_clk => system_clk, + system_reset => dram_sys_rst, + core_alt_reset => core_alt_reset, + pll_locked => system_clk_locked, + + wb_in => wb_dram_in, + wb_out => wb_dram_out, + wb_ctrl_in => wb_ext_io_in, + wb_ctrl_out => wb_dram_ctrl_out, + wb_ctrl_is_csr => wb_ext_is_dram_csr, + wb_ctrl_is_init => wb_ext_is_dram_init, + + init_done => dram_init_done, + init_error => dram_init_error, + + ddram_a => ddram_a, + ddram_ba => ddram_ba, + ddram_ras_n => ddram_ras_n, + ddram_cas_n => ddram_cas_n, + ddram_we_n => ddram_we_n, + ddram_cs_n => open, + ddram_dm => ddram_dm, + ddram_dq => ddram_dq, + ddram_dqs_p => ddram_dqs_p, + ddram_dqs_n => ddram_dqs_n, + ddram_clk_p => ddram_clk_p_vec, + ddram_clk_n => ddram_clk_n_vec, + ddram_cke => ddram_cke, + ddram_odt => ddram_odt, + ddram_reset_n => ddram_reset_n + ); + + d11_led <= not dram_init_done; + d12_led <= soc_rst; + d13_led <= dram_init_error; + + end generate; + + wb_ext_io_out <= wb_dram_ctrl_out; wb_sdcard_out.ack <= '0'; wb_sdcard_out.stall <= '0'; @@ -238,8 +368,4 @@ begin ext_rst_n <= '1'; - d11_led <= '0'; - d12_led <= soc_rst; - d13_led <= system_clk; - end architecture behaviour; diff --git a/microwatt.core b/microwatt.core index 799ee21..a379444 100644 --- a/microwatt.core +++ b/microwatt.core @@ -355,19 +355,21 @@ targets: antmicro-artix-dc-scm: default_tool: vivado - filesets: [core, antmicro-artix-dc-scm, soc, fpga, debug_xilinx, uart16550, xilinx_specific] + filesets: [core, antmicro-artix-dc-scm, soc, fpga, debug_xilinx, litedram, uart16550, xilinx_specific] parameters : - memory_size - ram_init_file + - use_litedram=true - clk_input - clk_frequency - disable_flatten_core + - no_bram - log_length=2048 - uart_is_16550 - has_uart1 - has_fpu - has_btc - generate: [git_hash] + generate: [litedram_nexys_video, git_hash] tools: vivado: {part : xc7a100tfgg484-1} toplevel : toplevel