Forum Discussion

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

Qsys DDR2 simulation with memory model - I'm missing something simple....

Hi all,

I'm moving into using DDR and DDR2 memory so I thought I would get myself up to speed by creating the simplest DDR2 simulation I could in qsys. Pity I couldn't get it to work....

simulation without a memory model

http://www.alteraforum.com/forum/attachment.php?attachmentid=9692&stc=1

You don't get much simpler than this. A DDR2 controller with its AMM slave exported. I ran a simulation of this successfully with the DDR2 controller attempting to initialise the memory. However, as there is no memory model, it doesn't initialise properly as expected. However, so far so good.

simulation with a memory model

The next stage is to add the memory model. To do this, I used some of methods used in this tutorial: http://www.altera.com/education/demonstrations/qsys/simulation/simulation-online-demo.html

In particular, I asked qsys to produce a test bench by adding BFM modules to the i/o.

http://www.alteraforum.com/forum/attachment.php?attachmentid=9693&stc=1

This process produces a new qsys model with BFM modules added. This includes DDR2 memory model connected to the DDR2 controller.

http://www.alteraforum.com/forum/attachment.php?attachmentid=9694&stc=1

Unfortunately, when I try and compile this, it doesn't like the memory model.

--- Quote Start ---

Error: sdram_my_partner: Altera DDR2 Memory Model for UniPHY does not support the QUARTUS_SYNTH fileset

Error: sdram_my_partner: An error occurred

while executing

"error "An error occurred""

(procedure "_error" line 8)

invoked from within

"_error "[get_module_property DESCRIPTION] does not support the QUARTUS_SYNTH fileset""

(procedure "generate_synth" line 2)

invoked from within

"generate_synth alt_mem_if_ddr2_mem_model_top_mem_if_dm_pins_en"

--- Quote End ---

Now the DDR2 controller uses ALTMEMPHY as I'm on cyclone III and UniPHY isn't an option. However, the memory model is for UniPHY. This might be the cause of the issue.

Any other ideas?

I'm targeting the Cyclone III as I had problems simulating with the Cyclone IV. I might try Cyclone V with the UniPHY as I think this is an option. I hit the same problem with Quartus 13.0 and 13.1.

2 Replies

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

    Get some external memory model for simulation, connect it to your design directly in Verilog simulation files, not in QSYS. Doing that you should not care if it's UniPHY or ALTMEMPHY. Micron provides nice models. Do not add manually BFMs, they will be generated by QSYS by default for simulation.

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

    Thanks linas, that hint was what I needed.

    For those coming across this later, this is what I ended up doing.

    I downloaded the Micron DDR2 model from here: http://www.micron.com/-/media/documents/products/sim%20model/dram/dram/3944512mb_ddr2.zip

    I modified ddr2_parameters.vh to include

    `define sg37E

    `define x16

    I then created a qsys system with just a DDR2 controller

    https://www.alteraforum.com/forum/attachment.php?attachmentid=9706

    (burst length was increased to 8)

    https://www.alteraforum.com/forum/attachment.php?attachmentid=9707

    Generation included simulation but didn't include producing the test bench.

    https://www.alteraforum.com/forum/attachment.php?attachmentid=9708

    Next was my test bench. (Yes I know there are better ways of driving the signals. This is just a quick hack)

    `timescale 1 ps / 1 ps
    module microntest_TB ();
    	reg  amms_address = 23'd0;            //   amms.address
    	reg        amms_write = 1'd0;              //       .write
    	reg        amms_read = 1'd0;               //       .read
    	reg        amms_beginbursttransfer = 1'd0; //       .beginbursttransfer
    	wire        amms_waitrequest_n;      //       .waitrequest_n
    	wire  amms_readdata;           //       .readdata
    	wire        amms_readdatavalid;      //       .readdatavalid
    	reg  amms_writedata = 64'd0;          //       .writedata
    	reg   amms_byteenable = 8'd0;         //       .byteenable
    	reg   amms_burstcount = 3'd0;         //       .burstcount
    	wire        ext_local_refresh_ack;   //    ext.local_refresh_ack
    	wire        ext_local_init_done;     //       .local_init_done
    	wire        ext_reset_phy_clk_n;     //       .reset_phy_clk_n
    	wire   mem_mem_odt;             //    mem.mem_odt
    	wire   mem_mem_clk;             //       .mem_clk
    	wire   mem_mem_clk_n;           //       .mem_clk_n
    	wire   mem_mem_cs_n;            //       .mem_cs_n
    	wire   mem_mem_cke;             //       .mem_cke
    	wire  mem_mem_addr;            //       .mem_addr
    	wire   mem_mem_ba;              //       .mem_ba
    	wire        mem_mem_ras_n;           //       .mem_ras_n
    	wire        mem_mem_cas_n;           //       .mem_cas_n
    	wire        mem_mem_we_n;            //       .mem_we_n
    	wire  mem_mem_dq;              //       .mem_dq
    	wire   mem_mem_dqs;             //       .mem_dqs
    	wire   mem_mem_dqs_n;             //       .mem_dqs
    	wire   mem_mem_rdqs_n;             //       .mem_dqs
    	wire   mem_mem_dm;              //       .mem_dm
    	reg        clk_clk = 1'd1;                 //    clk.clk
    	reg        sreset_reset_n = 1'd1;          // sreset.reset_n
    	reg        greset_reset_n = 1'd1;           // greset.reset_n
    	wire       sysclk_clk;                 //    sysclk.clk
    	always begin
    # 10000
    		clk_clk <= !clk_clk;
    	end
    	always @ (posedge ext_local_init_done) begin
    # 990000
    		amms_write = 1'd1;
    		amms_writedata = 64'h1234_5678_1122_3344;
    		amms_address = 8'h2;
    		amms_byteenable = 8'b11111111;
    		amms_beginbursttransfer = 1'b1;
    		amms_burstcount = 3'd1;
    # 13333
    		amms_write = 1'd1;
    		amms_writedata = 64'hAABB_CCDD_AAAA_BBBB;
    		amms_address = 8'h13;
    		amms_byteenable = 8'b11111111;
    		amms_beginbursttransfer = 1'b1;
    # 13333
    		amms_write = 1'd1;
    		amms_writedata = 64'h1111_2222_3333_4444;
    		amms_address = 8'h24;
    		amms_byteenable = 8'b11111111;
    		amms_beginbursttransfer = 1'b1;
    # 13333
    		amms_beginbursttransfer = 1'b0;
    		amms_write = 1'd0;
    		amms_writedata = 64'h0000_0000_0000_0000;
    		amms_address = 8'h0;
    		amms_byteenable = 8'b0000_0000;
    # 400000
    		amms_read = 1'd1;
    		amms_address = 8'h2;
    		amms_byteenable = 8'b11111111;
    # 13333
    		amms_read = 1'd0;
    # 400000
    		amms_read = 1'd1;
    		amms_address = 8'h13;
    		amms_byteenable = 8'b11111111;
    # 13333
    		amms_read = 1'd0;
    	end
    	
    	
    	
        microntest uut (
            .amms_address            (amms_address),            //   amms.address
            .amms_write              (amms_write),              //       .write
            .amms_read               (amms_read),               //       .read
            .amms_beginbursttransfer (amms_beginbursttransfer), //       .beginbursttransfer
            .amms_waitrequest_n      (amms_waitrequest_n),      //       .waitrequest_n
            .amms_readdata           (amms_readdata),           //       .readdata
            .amms_readdatavalid      (amms_readdatavalid),      //       .readdatavalid
            .amms_writedata          (amms_writedata),          //       .writedata
            .amms_byteenable         (amms_byteenable),         //       .byteenable
            .amms_burstcount         (amms_burstcount),         //       .burstcount
            .ext_local_refresh_ack   (ext_local_refresh_ack),   //    ext.local_refresh_ack
            .ext_local_init_done     (ext_local_init_done),     //       .local_init_done
            .ext_reset_phy_clk_n     (ext_reset_phy_clk_n),     //       .reset_phy_clk_n
            .mem_mem_odt             (mem_mem_odt),             //    mem.mem_odt
            .mem_mem_clk             (mem_mem_clk),             //       .mem_clk
            .mem_mem_clk_n           (mem_mem_clk_n),           //       .mem_clk_n
            .mem_mem_cs_n            (mem_mem_cs_n),            //       .mem_cs_n
            .mem_mem_cke             (mem_mem_cke),             //       .mem_cke
            .mem_mem_addr            (mem_mem_addr),            //       .mem_addr
            .mem_mem_ba              (mem_mem_ba),              //       .mem_ba
            .mem_mem_ras_n           (mem_mem_ras_n),           //       .mem_ras_n
            .mem_mem_cas_n           (mem_mem_cas_n),           //       .mem_cas_n
            .mem_mem_we_n            (mem_mem_we_n),            //       .mem_we_n
            .mem_mem_dq              (mem_mem_dq),              //       .mem_dq
            .mem_mem_dqs             (mem_mem_dqs),             //       .mem_dqs
            .mem_mem_dm              (mem_mem_dm),              //       .mem_dm
            .clk_clk                 (clk_clk),                 //    clk.clk
            .sreset_reset_n          (sreset_reset_n),          // sreset.reset_n
            .greset_reset_n          (greset_reset_n),           // greset.reset_n
            .sysclk_clk              (sysclk_clk)               // sysclk.clk
    		);
        ddr2 ddr_inst (
            .ck			(mem_mem_clk), 
            .ck_n		(mem_mem_clk_n),
            .cke		(mem_mem_cke), 
            .cs_n		(mem_mem_cs_n),
            .ras_n		(mem_mem_ras_n), 
            .cas_n		(mem_mem_cas_n), 
            .we_n		(mem_mem_we_n), 
            .dm_rdqs 	(mem_mem_dm),
            .ba			(mem_mem_ba), 
            .addr		(mem_mem_addr), 
            .dq			(mem_mem_dq), 
            .dqs		(mem_mem_dqs),
            .dqs_n		(mem_mem_dqs_n),
            .rdqs_n		(mem_mem_rdqs_n),
            .odt		(mem_mem_odt)
        );
    	
    endmodule
    

    This code, instantiates the qsys module then connects it to the Micron memory model.

    Finally, I put a script together to run the simulation

    set TOP_LEVEL_NAME "microntest_TB"
    set QSYS_SIMDIR "microntest/simulation"
    source $QSYS_SIMDIR/mentor/msim_setup.tcl
    dev_com
    com
    vlog ddr2.v
    vlog microntest_TB.v
    elab
    add wave *
    run 80 us
    

    Hopefully that is of help to someone.