UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Reply

SP605 DDR3 addressing

Observer
Posts: 26
Registered: ‎11-06-2015

SP605 DDR3 addressing

Hi, the following post is quite long, but since I have had trouble making the SP605 board properly interact with the DDR3 for over a month now, hopefully this will be useful to others in the same situation as I find myself in. I am pretty certain it's a simple configuration or conceptual error, but I would be more than happy to have this resolved soon.

 

=============================

SCENARIO:

 

I have created a USB-UART interface to communicate with the FPGA and control the DDR3. Using the IP generator in ISE, I generated a MIG wrapper and then I designed the memory interface controller. However, I have referenced manuals ug388 and ug416, but I have not been able to have the DDR3 behave as expected.

 

=============================

PROBLEM STATEMENT:

 

Playing around with the burst lengths for write and read commands, I am able to get data back from the DDR3, yet the addressing scheme does not seem to be correct as data is duplicated in addresses 0 and 1, 2 and 3, 4 and 5, and so forth. Also, whenever I write into address 0, for example, nothing changes. Then, when I write into address 1, both addresses 0 and 1 are updated with the data value I just sent. It seems I am "losing" half of the memory space due to this coupled effect.

 

=============================

DDR3 IP CONFIGURATION:

 

The setup for the DDR3 using the IP generator – considering the SP605 board scenario – is listed below. In sum, I activated the DDR3 Bank 3 and configured Port0 to be 32-bit bidirectional.

 

Memory selection:

> Enable AXI interface: unchecked

> Use extended MCB performance range: unchecked

> Memory type for bank 3: DDR3 SDRAM

> Memory type for bank 1: none

 

Options for C3 – DDR3 SDRAM

> Frequency: 400 MHz

> Memory part: MTJ41J64M16XX-187E

 

Memory options for C3 – DDR3 SDRAM

> Output driver impedance control: RZQ/6

> RTT (nominal) – ODT: RZQ/4

> Auto self refresh: enabled

 

Port configuration for C3 – DDR3 SDRAM

> Two 32-bit bi-directional and four 32-bit unidirectional ports

> Port0: checked

> Port1: unchecked

> Port2: unchecked

> Port3: unchecked

> Port4: unchecked

> Port5: unchecked

> Memory address mapping selection: row-bank-column

 

FPGA options for C3 – DDR3 SDRAM

> Memory interface pin termination: Calibrated input termination

> Select RZQ pin location: R7

> Select ZIO pin location: W4

> Debug signals for memory controller: disable

> System clock: differential

 

=============================

DATA STRUCTURE:

 

From Matlab, I send in a 64-bit command which should write or read the DDR3 based on the address and data provided in this command.

 

wire [00:00] cmd_instruction = usb_data[63:63];          // ‘0’ = write; ‘1’ = read
wire [27:00] cmd_address = usb_data[62:37];             // 26-bit address
wire [31:00] cmd_data = usb_data[31:00];                   // 32-bit data

 

In ug388, the following can be extracted:

 

Page 20: The address is 26 bits wide.

> C_MEM_ADDR_WIDTH = 13

> C_MEM_BANKADDR_WIDTH = 3

> C_MEM_NUM_COL_BITS = 10

> C_P0_DATA_PORT_SIZE = 32         // 32-bit data ports

> C_P0_MASK_SIZE = 4                      // 4 bytes = 32 bits (each mask bit represents an entire data byte)

 

Pages 26-27: Command data structure.

> pX_cmd_addr[29:0]: 30-bit address, however the last two bits should = “00” since every word (32 bits) is formed by 4 bytes.

> pX_cmd_bl[5:0]: Burst length of 1 is obtained by setting this signal to 0.

> pX_cmd_instr[2:0]: The only command instructions used are write=”000” and read=”001”.

 

Page 28: Write data structure.

> pX_wr_mask[PX_MASKSIZE-1:0]: 4-bit mask is set to “0000” so that all 4 bytes are always written into the memory.

 

=============================

SIGNAL ASSIGNMENTS:

 

Using all this information, I assigned my signals in the following manner:

assign p0_mcb_cmd_instr = {2'b00, cmd_instruction};
assign p0_mcb_cmd_addr = {2’d0, cmd_address, 2'd0};
assign p0_mcb_cmd_bl = 6'd0;

assign p0_mcb_wr_data = cmd_data;

assign p0_mcb_wr_mask = 4'd0;

 

=============================

CONCLUSIONS:

 

Based on the configuration, does anyone know what the expected behavior of my controller should be?

If any additional information is necessary for clarification, please let me know.

 

Thanks a lot,

Bruno.

Observer
Posts: 26
Registered: ‎11-06-2015

Re: SP605 DDR3 addressing

One last thing:

 

Pages 51 and 61-62 give additional information as to the address mapping. Also, Table 4-5 (pg. 63) shows how the 2 MSBs and 2 LSBs for the "DDR3, x16, 1 Gb" should not be used and match the assignment in the Verilog code:

 

assign p0_mcb_cmd_addr = {2’d0, cmd_address, 2'd0};

Xilinx Employee
Posts: 4,131
Registered: ‎07-11-2011

Re: SP605 DDR3 addressing

[ Edited ]

@bpedroni, What is your memory burst length? There are known issues with IP accessing same addresses with BL4.

If it is 4 please try to set it for 8 and see how it goes

 

 

-Vanitha

 

---------------------------------------------------------------------------------------------
Please do google search before posting, you may find relavant information.
Mark the post - "Accept as solution" and give kudos if information provided is helpful and reply oriented
Observer
Posts: 26
Registered: ‎11-06-2015

Re: SP605 DDR3 addressing

Hi @vsrunga,

 

The MIG already generated it set to 8.

 

localparam C3_MEM_BURST_LEN = 8;

 

Thanks,

Bruno.

Visitor
Posts: 9
Registered: ‎03-13-2016

Re: SP605 DDR3 addressing

HI @bpedroni

 

My design is exactly same as your design, using USB-UART interface to communicate with the FPGA and control the DDR3. I am also facing same issue, data is duplicated in addresses 0 and 1, 2 and 3, 4 and 5, and so forth.

 

Have you got any solution? could you please share with me. it will be helpful for me. 

Observer
Posts: 26
Registered: ‎11-06-2015

Re: SP605 DDR3 addressing

Hi @mam12, I have been able to fix some things but there are still issues.

 

My current scenario (to which I have designed a "bug" workaround, yet taking up additional clock cycles) is the following:

* Bug 1: the DDR3 writes into the previous address speficied in cmd_address, so the write function shifts the address by 1.
* Bug 2: the last DDR3 read word is always incorrect, so the burst length and DDR3 read were adapted as to return only meaningful data (burstFIFO was created).

 

I would be happy to share my code with you and maybe we could help each other out. I plan on doing a Youtube tutorial on how to configure the DDR3 using Spartan-6 because it has been a nightmare.

Visitor
Posts: 9
Registered: ‎03-13-2016

Re: SP605 DDR3 addressing

Hi @bpedroni

 

Thanks for reply.

 

Could you share your code so that i may get some ideas to solve the issues or even I would be happy to share my code with you. 

you can look at my code and let me know if any corrections are required. 

 

Its really good idea to do Youtube tutorial on configure the DDR3. It will help may people like me. 

Observer
Posts: 26
Registered: ‎11-06-2015

Re: SP605 DDR3 addressing

@vsrunga

 

Hello, I have finally been able to configure the DDR3 appropriately and get reliable results. For my sake, I have written a walkthru of how to perform this configuration.

 

Therefore, I was wondering if it would be OK with you guys (i.e. Xilinx) if I attach the PDF here in the forum so others can benefit from my experience in this issue.

 

Best,

Bruno.

Moderator
Posts: 3,270
Registered: ‎02-06-2013

Re: SP605 DDR3 addressing

Hi

 

Feel free to share any docs you want to share that will help other users on similar issue. 

Regards,

Satish

--------------------------------------------------​--------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful.
--------------------------------------------------​-------------------------------------------
Visitor
Posts: 9
Registered: ‎03-13-2016

Re: SP605 DDR3 addressing

Hi,

 

As i explained earlier i m facing some issue with DDR3 read write operation. 

 

I m using serial communication to control the DDR3 read/write. when i try to read and write continuously, some write/read locations data getting corrupted.  

 

my targeted device is spartan 6 evolution kit SP605.

 

kindly have a look on my code (given below) and let me know if any correction or where exactly i m going wrong.

 

PORT0 for write

 

   DDR_P0_IN:Process(CLK_OUT1_100MHZ, mem_ready)      
    variable state_write        :     integer range 0 to 100 := 1;
    variable pre_write_control  :    std_logic:= '0';
    variable count        :    integer range 0 to 63 := 0;

    begin
    if mem_ready = '1' then
        if rising_edge(CLK_OUT1_100MHZ)then
                    case state_write is
                    when 1 =>
                        ddr3_busy_bit_write <='1';
                        c3_p0_cmd_en <= '1';                        -- enable command
                        c3_p0_cmd_instr <= "010";--"010";    -- write with auto precharge cmnd
                        c3_p0_wr_mask <= "11111100";
                        c3_p0_cmd_bl <= "000001";                -- Value 63 for block length 64
                        c3_p0_cmd_byte_addr <= "000"& ddr3_write_address & "000";
                        state_write := 2;

                    when 2 =>
                        c3_p0_cmd_en <= '0';                        -- disable cmnd
                        c3_p0_wr_data <= x"000000000000" & ddr3_data;
                        c3_p0_wr_en <= '1';                        -- Enable write
                        state_write := 3;                        -- Go to next state
                        
                    when 3 =>
                        c3_p0_wr_en <= '0';                        -- disable write            
                        if((c3_p0_wr_empty = '0') )then      
                            state_write := 4;                  
                        else
                            state_write := 3;
--                            led_s(1) <= not led_s(1);
                        end if;
                    
                    when 4 =>
                        if(c3_p0_wr_empty = '1')then     
                            c3_p0_wr_en <= '0';
                            state_write := 5;    
                        else
                            state_write := 4;
                            led_s(2) <= not led_s(2);
                        end if;
                    when 5 =>
                        mem_write_cmp_sig <= not mem_write_cmp_sig;
                         ddr3_busy_bit_write <= '0';
                        state_write := 1;
                    when others =>    
                        state_write := 1;
                    end case;
                else
                        c3_p0_cmd_en <= '0';                        -- Init/idle values
                        c3_p0_cmd_instr <= "000";
                        c3_p0_cmd_bl <= "000000";
                        c3_p0_cmd_byte_addr <= (others =>'0');
                        c3_p0_wr_mask <= "00000000";
                        c3_p0_wr_en <= '0';
                        c3_p0_wr_data <= (others => '0');
                end if;
        end if;
    end if;
end process;

 

 

Port1 for read:

 

DDR_P1_OUT:Process(CLK_OUT1_100MHZ, mem_ready)       -- Block read test
    variable pre_read_control    :     std_logic:= '0';
    variable state                :     integer range 0 to 100 := 1;
    variable Count                :     integer range 0 to 3 := 0;

begin

    if mem_ready='1' then
        if rising_edge(CLK_OUT1_100MHZ)then
               case state is
                when 1 =>
                    ddr3_busy_bit_read <='1';
                    c3_p1_wr_mask <= "11111100";
                    c3_p1_cmd_instr <= "011";--"011";       
                    c3_p1_cmd_bl <= "000001";                 
                    c3_p1_cmd_byte_addr <= "000"& ddr3_read_address & "000" ;
                    c3_p1_cmd_en <= '1';
                    state := 2;
                when 2 =>
                    c3_p1_cmd_en <= '0';                            -- Enable cammand
                    c3_p1_rd_en <= '1';
                    state := 3;
                    
            when 3 =>
                    if(c3_p1_rd_empty = '0')then                -- If data is ready
                        ddr3_dataout <= c3_p1_rd_data (15 downto 0);
--                        led_s <= c3_p1_rd_data (3 downto 0);
                        state := 41;
                    else
                        state := 3;
                        led_s(0) <= not led_s(0);
                    end if;
            
                When 4 =>
                    if (c3_p1_rd_empty = '1')then
                        mem_read_sig <= not mem_read_sig;
                         ddr3_busy_bit_read <= '0';
                        c3_p1_rd_en <= '0';
                        state := 1;
                    else
                        state := 4;
                        led_s(3) <= not led_s(3);
                    end if;
                when others =>
                    state := 1;
                end case;
            end if;
        end if;
    end if;
end process;