Thursday 22 May 2014

Connecting the SDRAM to a Nios II on the DE0-Nano

I my last post Simple Nios II on the DE0-Nano I create a Nios II Processor from scratch. The Nios II design used 20K Bytes of On-Chip memory to store and execute its program. Having 20K of RAM is only enough for the most simple of applications. Lucky the DE0-Nano has 32Mbytes of SDRAM. This is plenty of RAM to do lots of complex algorithms. This post looks at how to attach the 23Mbytes of SDRAM to a Nios II running on the DE0-Nano demo board.

What is SDRAM

Synchronous Dynamic Random Access Memory or SDRAM is memory that is synchronized to the system clock. The memory is divided into a number of different banks allowing the memory to use a number of them at the same time. This can result in higher data rates than it non-synchronous equivalent DRAM.

Qsys

Building on the design produced in xx we need to add the SDRAM controller block to our Qsys design for the Nios II system.


Once the component is added we need to connect it to the Nios processor. Make sure that both the data and instruction buses are connected. 


One the SDRAM controller is connected we need to chance the reset and exception addresses from their location within on-chip ram to their new location within the SDRAM.  


Once the Nios II reset and exceptions are changed we can generate our Qsys model and close Qsys. We now need to modify our VHDL to connect in the SDRAM.

VHDL


The VHDL was updated with a new Qsys component that included the extra signals needed to access the SDRAM:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity de0nano1 is
   port
    (
     pin_clk         : in    std_logic;
     pin_reset_n     : in    std_logic;
     pin_led_pio     : out   std_logic_vector(7 downto 0);
     pin_sdram_addr  : out   std_logic_vector(12 downto 0);            pin_sdram_ba    : out   std_logic_vector(1 downto 0);            pin_sdram_cas_n : out   std_logic;                                pin_sdram_cke   : out   std_logic;                                pin_sdram_cs_n  : out   std_logic;                                pin_sdram_dq    : inout std_logic_vector(15 downto 0) := (others => 'X'); 
     pin_sdram_dqm   : out   std_logic_vector(1 downto 0);            pin_sdram_ras_n : out   std_logic;                                pin_sdram_we_n  : out   std_logic;
     pin_sdram_clk   : out   std_logic
     );
end entity;

architecture arch_de0nano1 of de0nano1 is

  component my_nios1 is
    port 
    (
     clk_clk              : in  std_logic := 'X'; 
     reset_reset_n        : in  std_logic := 'X'; 
     led_pio_external_connection_export : out std_logic_vector(7 downto 0);
     sdram_addr           : out   std_logic_vector(12 downto 0); 
     sdram_ba             : out   std_logic_vector(1 downto 0);  
     sdram_cas_n          : out   std_logic;                     
     sdram_cke            : out   std_logic;                     
     sdram_cs_n           : out   std_logic;                     
     sdram_dq             : inout std_logic_vector(15 downto 0) := (others => 'X'); 
     sdram_dqm            : out   std_logic_vector(1 downto 0);  
     sdram_ras_n          : out   std_logic;                     
     sdram_we_n           : out   std_logic                      
      );
  end component my_nios1;
  
begin

  inst_nios: component my_nios1 port map 
    (
      clk_clk                            => pin_clk, 
      reset_reset_n                      => pin_reset_n, 
      led_pio_external_connection_export => pin_led_pio,
      sdram_addr                         => pin_sdram_addr, 
      sdram_ba                           => pin_sdram_ba, 
      sdram_cas_n                        => pin_sdram_cas_n ,  
      sdram_cke                          => pin_sdram_cke,  
      sdram_cs_n                         => pin_sdram_cs_n,  
      sdram_dq                           => pin_sdram_dq, 
      sdram_dqm                          => pin_sdram_dqm ,  
      sdram_ras_n                        => pin_sdram_ras_n,   
      sdram_we_n                         => pin_sdram_we_n  
    );
 
    pin_sdram_clk <= pin_clk;
 
end architecture arch_de0nano1;

When complied this VHDL will create the following RTL. It is interesting to note that the SDRAM clock is being driven directly by the system clock. However even though this design works it would be better to drive the clock line from a PLL. I will discuss this in a future post.


Before we compile our final design we must assign the correct pin to make the physical connection on our DE0-Nano device. I have include the TCL below to illiterate the connections made:

set_location_assignment PIN_A15 -to pin_led_pio[0]
set_location_assignment PIN_A13 -to pin_led_pio[1]
set_location_assignment PIN_B13 -to pin_led_pio[2]
set_location_assignment PIN_A11 -to pin_led_pio[3]
set_location_assignment PIN_D1 -to pin_led_pio[4]
set_location_assignment PIN_F3 -to pin_led_pio[5]
set_location_assignment PIN_B1 -to pin_led_pio[6]
set_location_assignment PIN_L3 -to pin_led_pio[7]

set_location_assignment PIN_E1 -to pin_reset_n
set_location_assignment PIN_R8 -to pin_clk

set_location_assignment PIN_L4 -to pin_sdram_addr[12]
set_location_assignment PIN_N1 -to pin_sdram_addr[11]
set_location_assignment PIN_N2 -to pin_sdram_addr[10]
set_location_assignment PIN_P1 -to pin_sdram_addr[9]
set_location_assignment PIN_R1 -to pin_sdram_addr[8]
set_location_assignment PIN_T6 -to pin_sdram_addr[7]
set_location_assignment PIN_N8 -to pin_sdram_addr[6]
set_location_assignment PIN_T7 -to pin_sdram_addr[5]
set_location_assignment PIN_P8 -to pin_sdram_addr[4]
set_location_assignment PIN_M8 -to pin_sdram_addr[3]
set_location_assignment PIN_N6 -to pin_sdram_addr[2]
set_location_assignment PIN_N5 -to pin_sdram_addr[1]
set_location_assignment PIN_P2 -to pin_sdram_addr[0]

set_location_assignment PIN_K1 -to pin_sdram_dq[15]
set_location_assignment PIN_N3 -to pin_sdram_dq[14]
set_location_assignment PIN_P3 -to pin_sdram_dq[13]
set_location_assignment PIN_R5 -to pin_sdram_dq[12]
set_location_assignment PIN_R3 -to pin_sdram_dq[11]
set_location_assignment PIN_T3 -to pin_sdram_dq[10]
set_location_assignment PIN_T2 -to pin_sdram_dq[9]
set_location_assignment PIN_T4 -to pin_sdram_dq[8]
set_location_assignment PIN_R7 -to pin_sdram_dq[7]
set_location_assignment PIN_J1 -to pin_sdram_dq[6]
set_location_assignment PIN_J2 -to pin_sdram_dq[5]
set_location_assignment PIN_K2 -to pin_sdram_dq[4]
set_location_assignment PIN_K5 -to pin_sdram_dq[3]
set_location_assignment PIN_L8 -to pin_sdram_dq[2]
set_location_assignment PIN_G1 -to pin_sdram_dq[1]
set_location_assignment PIN_G2 -to pin_sdram_dq[0]
set_location_assignment PIN_T5 -to pin_sdram_dqm[1]
set_location_assignment PIN_R6 -to pin_sdram_dqm[0]

set_location_assignment PIN_M6 -to pin_sdram_ba[1]
set_location_assignment PIN_M7 -to pin_sdram_ba[0]

set_location_assignment PIN_L1 -to pin_sdram_cas_n
set_location_assignment PIN_L7 -to pin_sdram_cke
set_location_assignment PIN_R4 -to pin_sdram_clk
set_location_assignment PIN_P6 -to pin_sdram_cs_n
set_location_assignment PIN_L2 -to pin_sdram_ras_n
set_location_assignment PIN_C2 -to pin_sdram_we_n

Eclipse

The last thing to do before we can make use of our connected SDRAM is change some of the compiler setting in Eclipse to pint to the external of memory.  






Finally we can now true off the reduced device driver and small c library. We can also have enough memory to support the C++ library if needed.  



That it we have now added external SDRAM to our Nios II running on the DE0-Nano. Do not forget it is better to use a PLL to drive the clock. I will chat about this in my next post.

References




No comments:

Post a Comment