Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
9 years ago

Writing a LPDDR controller without IP

Hello, guys.

I have tried to write a controller for the LPDDR2 without IP to understand that what is the DDR and how to control it.

The good news is the Micron provides a stub for simulations (it simulates the memory module),

so I only have to write a controller.

Bad news is not compilable that I wrote (errors in the fitting)...

The error message is:

169008 Can't turn on open-drain option for differential I/O pin <pin-name>

I have googled what is the open-drain, but I think it does not need because they will use same power source;

the pins DQS/DQS_n of the LPDDR2(MT42L128M32D1LF-25WT) allows 1.14~1.30 Volts,

and an I/O standard of the pins DDR2LP_DQS_p/_n[0~3] is "Differential 1.2-V HSUL".

Additionally, there are no words such as "drain" existing in the micron's catalog.

So I have turned off the option "Auto Open-Drain Pins", but it still raises error.

The message is:

Error (169290): Can't place differential I/O positive pin <pin-name> at a differential I/O negative location <location>(PAD_<number>)

The codes I wrote is below;

utility.vhd: (partial)

library ieee;
use ieee.std_logic_1164.all;
entity LPDDR2_controller is
    port (
        -- Command/address inputs
        CA: out std_logic_vector(9 downto 0);
        -- Clock
        CK_p: out std_logic;
        CK_n: out std_logic;
        -- Clock enable
        CKE: out std_logic_vector(1 downto 0);
        -- Chip Select
        CS_n: out std_logic_vector(1 downto 0);
        -- Input data mask
        DM: out std_logic_vector(3 downto 0);
        -- Data input/output
        DQ: inout std_logic_vector(31 downto 0);
        -- Data strobe
        DQS_p: inout std_logic_vector(3 downto 0);
        DQS_n: inout std_logic_vector(3 downto 0);
        -- External impedance (240 ohm)
        ZQ: in std_logic
    );
end;
architecture controller of LPDDR2_controller is
begin
    CA <= "0000000111"; -- NOP
    CK_p <= '0';
    CK_n <= '1';
    CKE <= "00";
    CS_n <= "00";
    DM <= "0000";
    DQ <= (others => '0');
    DQS_p <= (others => '0');
    DQS_n <= (others => '1');
end;

main.vhd: (partial)

library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use work.all;
entity main is
    port (
        CLOCK_125_p: in std_logic;
        CPU_RESET_n: in std_logic;
        DDR2LP_CA: out std_logic_vector(9 downto 0);
        DDR2LP_DQ: inout std_logic_vector(31 downto 0);
        DDR2LP_DQS_p: inout std_logic_vector(3 downto 0);
        DDR2LP_DQS_n: inout std_logic_vector(3 downto 0);
        DDR2LP_DM: out std_logic_vector(3 downto 0);
        DDR2LP_CK_p: out std_logic;
        DDR2LP_CK_n: out std_logic;
        DDR2LP_CKE: out std_logic_vector(1 downto 0);
        DDR2LP_CS_n: out std_logic_vector(1 downto 0);
        DDR2LP_OCT_RZQ: in std_logic
    );
end;
architecture main of main is
    component LPDDR2_controller
        port (
            CA: out std_logic_vector(9 downto 0);
            CK_p: out std_logic;
            CK_n: out std_logic;
            CKE: out std_logic_vector(1 downto 0);
            CS_n: out std_logic_vector(1 downto 0);
            DM: out std_logic_vector(3 downto 0);
            DQ: inout std_logic_vector(31 downto 0);
            DQS_p: inout std_logic_vector(3 downto 0);
            DQS_n: inout std_logic_vector(3 downto 0);
            ZQ: in std_logic
        );
    end component;
begin
    mem: LPDDR2_controller
        port map(
            CA => DDR2LP_CA,
            CK_p => DDR2LP_CK_p,
            CK_n => DDR2LP_CK_n,
            CKE => DDR2LP_CKE,
            CS_n => DDR2LP_CS_n,
            DM => DDR2LP_DM,
            DQ => DDR2LP_DQ,
            DQS_p => DDR2LP_DQS_p,
            DQS_n => DDR2LP_DQS_n,
            ZQ => DDR2LP_OCT_RZQ
        );
    -- and do something which does not touch to the memory...
end;

How to take the negative pins?

or should I write to implement more features at the controller (e.g. reset the memory)?

Thank you for reading!

Environment Info:

Windows 7 Ultimate Service Pack 1

Quartus Prime Version 16.0.2 Build 222 07/20/2016 SJ Lite Edition

Cyclone V GX Starter Kit (5CGXFC5C6F27C7)

1 Reply

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I am sorry for reading the previous.

    I have succeeded to avoid the errors myself.

    The way to use differential pins is to use ALTIOBUF_XXX Mega-Functions like below;

    library ieee, altera_mf;
    use ieee.std_logic_1164.all;
    use altera_mf.altera_mf_components.all;
    entity LPDDR2_controller is
    	port (
    		-- Command/address inputs
    		CA: out std_logic_vector(9 downto 0);
    		-- Clock
    		CK_p: out std_logic;
    		CK_n: out std_logic;
    		-- Clock enable
    		CKE: out std_logic_vector(1 downto 0);
    		-- Chip Select
    		CS_n: out std_logic_vector(1 downto 0);
    		-- Input data mask
    		DM: out std_logic_vector(3 downto 0);
    		-- Data input/output
    		DQ: inout std_logic_vector(31 downto 0);
    		-- Data strobe
    		DQS_p: inout std_logic_vector(3 downto 0);
    		DQS_n: inout std_logic_vector(3 downto 0);
    		-- External impedance (240 ohm)
    		ZQ: in std_logic
    	);
    end;
    architecture controller of LPDDR2_controller is
    	signal dqs_out: std_logic_vector(3 downto 0);
    	signal ck_out: std_logic_vector(0 to 0);
    	signal ck_out_b: std_logic_vector(0 to 0);
    begin
    	CA <= "0000000111"; -- NOP
    	i0: altiobuf_out  -- HERE
    		generic map(
    			number_of_channels => 1,
    			use_differential_mode => "TRUE"
    		)
    		port map(
    			datain => "0",
    			dataout => ck_out,
    			dataout_b => ck_out_b
    		);
    	CK_p <= ck_out(0);
    	CK_n <= ck_out_b(0);
    	CKE <= "00";
    	CS_n <= "00";
    	DM <= "0000";
    	DQ <= (others => '0');
    	i1: altiobuf_bidir -- AND HERE
    		generic map(
    			number_of_channels => 4,
    			use_differential_mode => "TRUE"
    		)
    		port map(
    			datain => (others => '0'),
    			dataio => DQS_p,
    			dataio_b => DQS_n,
    			dataout => dqs_out,
    			oe => (others => '1')
    		);
    end;

    I will try to use this MFs. I will have to check that they work correctly...

    Thank you for reading.

    Post Script:

    Because the compiler raises a pretty critical warning to this code in my environment, I am going to search the next problem.