FC2カウンター FPGAの部屋 ビットマップ・ディスプレイ・コントローラの作製16(全体シミュレーション)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

ビットマップ・ディスプレイ・コントローラの作製16(全体シミュレーション)

ビットマップ・ディスプレイ・コントローラの作製15(デバック2)”の続き。

今回はだいぶ動かすにに苦労している。夏休みでお盆の行事をこなしながら、あいた時間にやっているが、なかなかうまく行かない。
今回はXPS全体でシミュレーションを行うことにした。PlanAheadでのシミュレーションのやり方は、”PlanAhead14.1でChipScope Proを試してみた1(ChipScope の設定)”、”PlanAhead14.1でChipScope Proを試してみた2(ChipScope Analyzer)”を参照。
早速、テストベンチを書いて、DDR2 SDRAMのモデルを接続した。DDR2 SDMRAMのモデルは以前使用したマイクロン社のモデルを借用した。

PlanAhead のシミュレーションの設定を下に示す。
BitMapDispCont_114_120816.png

VERILOG_DEFINE をsg25E; x16 に設定している。これはDDR2 SDRAMモデルのスピードグレードとデータバス幅の設定だ。DDR2 SDRAMのデータバス幅は16ビットに設定している。
テストベンチ (tb_system_stub.v) を下に示す。

//-----------------------------------------------------------------------------
// testbench.v
//-----------------------------------------------------------------------------

`timescale 1 ps / 100 fs

// START USER CODE (Do not remove this line)

// User: Put your directives here. Code in this
//       section will not be overwritten.

// END USER CODE (Do not remove this line)

module testbench
  (
  );

  `include "simulation/ddr2_parameters.vh";

  // START USER CODE (Do not remove this line)

  // User: Put your signals here. Code in this
  //       section will not be overwritten.

  // END USER CODE (Do not remove this line)

  real CLK_PERIOD = 10000.000000;
  real RESET_LENGTH = 160000;

  // Internal signals

  reg CLK;
  wire [0:7] Led;
  reg RESET;
    wire mcbx_dram_we_n;
    wire mcbx_dram_udm;
    wire mcbx_dram_ras_n;
    wire mcbx_dram_odt;
    wire mcbx_dram_ldm;
    wire mcbx_dram_clk_n;
    wire mcbx_dram_clk;
    wire mcbx_dram_cke;
    wire mcbx_dram_cas_n;
    wire [2:0] mcbx_dram_ba;
    wire [12:0] mcbx_dram_addr;
    reg axi_uartlite_0_RX_pin;
    wire axi_uartlite_0_TX_pin;
    wire zio;
    wire rzq;

    wire    [DQS_BITS-1:0] ddr2_dqs_fpga, ddr2_dqs_sdram;
    wire    [DQS_BITS-1:0] ddr2_dqs_n_fpga, ddr2_dqs_n_sdram;
    wire    [DQ_BITS-1:0] ddr2_dq_fpga, ddr2_dq_sdram;
    reg        [DQS_BITS-1:0] ddr2_dqs_fpgan, ddr2_dqs_sdramn;
    reg        [DQS_BITS-1:0] ddr2_dqs_n_fpgan, ddr2_dqs_n_sdramn;
    reg        [DQ_BITS-1:0] ddr2_dq_fpgan, ddr2_dq_sdramn;
    wire    [2:0] cmd;
    reg        sdram_clk;
    reg        sdram_clkb;
    reg        [12:0] sdram_address;
    reg        [2:0] sdram_ba;
    reg        sdram_cke;
    reg        sdram_rasb, sdram_casb, sdram_web;
    reg        [1:0] sdram_dmn;
    wire    [1:0] sdram_dm;
    reg        sdram_odt;
    wire        reset;
    reg        enable_o;

  system_stub
    dut (
      .RESET ( RESET ),
      .Led ( Led ),
      .CLK ( CLK ),
      .axi_uartlite_0_RX_pin ( axi_uartlite_0_RX_pin ),
      .axi_uartlite_0_TX_pin ( axi_uartlite_0_TX_pin ),
      .axi_s6_ddrx_0_mcbx_dram_addr ( mcbx_dram_addr ),
      .axi_s6_ddrx_0_mcbx_dram_ba ( mcbx_dram_ba ),
      .axi_s6_ddrx_0_mcbx_dram_ras_n ( mcbx_dram_ras_n ),
      .axi_s6_ddrx_0_mcbx_dram_cas_n ( mcbx_dram_cas_n ),
      .axi_s6_ddrx_0_mcbx_dram_we_n ( mcbx_dram_we_n ),
      .axi_s6_ddrx_0_mcbx_dram_cke ( mcbx_dram_cke ),
      .axi_s6_ddrx_0_mcbx_dram_clk ( mcbx_dram_clk ),
      .axi_s6_ddrx_0_mcbx_dram_clk_n ( mcbx_dram_clk_n ),
      .axi_s6_ddrx_0_mcbx_dram_dq ( ddr2_dq_fpga ),
      .axi_s6_ddrx_0_mcbx_dram_dqs ( ddr2_dqs_fpga[0] ),
      .axi_s6_ddrx_0_mcbx_dram_dqs_n ( ddr2_dqs_n_fpga[0] ),
      .axi_s6_ddrx_0_mcbx_dram_udqs ( ddr2_dqs_fpga[1] ),
      .axi_s6_ddrx_0_mcbx_dram_udqs_n ( ddr2_dqs_n_fpga[1] ),
      .axi_s6_ddrx_0_mcbx_dram_udm ( mcbx_dram_udm ),
      .axi_s6_ddrx_0_mcbx_dram_ldm ( mcbx_dram_ldm ),
      .axi_s6_ddrx_0_mcbx_dram_odt ( mcbx_dram_odt ),
      .axi_s6_ddrx_0_rzq ( rzq ),
      .axi_s6_ddrx_0_zio ( zio )
    );

  // Clock generator for CLK

  initial
    begin
      CLK = 1'b0;
      forever #(CLK_PERIOD/2.00)
        CLK = ~CLK;
    end

  // Reset Generator for RESET

  initial
    begin
      RESET = 1'b0;
      #(RESET_LENGTH) RESET = ~RESET;
    end

  // START USER CODE (Do not remove this line)

  // User: Put your stimulus here. Code in this
  //       section will not be overwritten.
    parameter DELAY_TIME = 2000; // 2nsec
    
    assign cmd = {mcbx_dram_ras_n, mcbx_dram_cas_n, mcbx_dram_we_n};
    
    assign reset = ~RESET;
    always @(posedge mcbx_dram_clk, posedge reset)
        if (reset)
            enable_o <= 1'b0;
        else
            if (cmd==3'b100)
                enable_o <= 1'b0;
            else if (cmd==3'b101)
                enable_o <= 1'b1;

    always @ *
        if (enable_o == 1'b1)
            ddr2_dqs_fpgan <= #DELAY_TIME ddr2_dqs_sdram;
        else
            ddr2_dqs_fpgan <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b1)
            ddr2_dqs_n_fpgan <= #DELAY_TIME ddr2_dqs_n_sdram;
        else
            ddr2_dqs_n_fpgan <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b1)
            ddr2_dq_fpgan <= #DELAY_TIME ddr2_dq_sdram;
        else
            ddr2_dq_fpgan <= #DELAY_TIME {DQ_BITS{1'bz}};

    always @ *
        if (enable_o == 1'b0)
            ddr2_dqs_sdramn <= #DELAY_TIME ddr2_dqs_fpga;
        else
            ddr2_dqs_sdramn <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b0)
            ddr2_dqs_n_sdramn <= #DELAY_TIME ddr2_dqs_n_fpga;
        else
            ddr2_dqs_n_sdramn <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b0)
            ddr2_dq_sdramn <= #DELAY_TIME ddr2_dq_fpga;
        else
            ddr2_dq_sdramn <= #DELAY_TIME {DQ_BITS{1'bz}};
    
    assign ddr2_dqs_fpga = ddr2_dqs_fpgan;
    assign ddr2_dqs_n_fpga = ddr2_dqs_n_fpgan;
    assign ddr2_dq_fpga = ddr2_dq_fpgan;
    assign ddr2_dqs_sdram = ddr2_dqs_sdramn;
    assign ddr2_dqs_n_sdram = ddr2_dqs_n_sdramn;
    assign ddr2_dq_sdram = ddr2_dq_sdramn;

    always @ * begin
        sdram_clk <= #DELAY_TIME mcbx_dram_clk;
        sdram_clkb <= #DELAY_TIME mcbx_dram_clk_n;
        sdram_address <= #DELAY_TIME mcbx_dram_addr;
        sdram_ba <= #DELAY_TIME mcbx_dram_ba;
        sdram_cke <= #DELAY_TIME mcbx_dram_cke;
        sdram_rasb <= #DELAY_TIME mcbx_dram_ras_n;
        sdram_casb <= #DELAY_TIME mcbx_dram_cas_n;
        sdram_web <= #DELAY_TIME mcbx_dram_we_n;
        sdram_dmn <= #DELAY_TIME {mcbx_dram_udm, mcbx_dram_ldm};
        sdram_odt <= #DELAY_TIME mcbx_dram_odt;
    end
    assign sdram_dm = sdram_dmn;
    
    ddr2 MT47H64M16_25E(
        .dq(ddr2_dq_sdram),
        .dqs(ddr2_dqs_sdram),
        .dqs_n(ddr2_dqs_n_sdram),
        .rdqs_n(),
        .addr(sdram_address),
        .ba(sdram_ba),
        .ck(sdram_clk),
        .ck_n(sdram_clkb),
        .cke(sdram_cke),
        .cs_n(1'b0),
        .ras_n(sdram_rasb),
        .cas_n(sdram_casb),
        .we_n(sdram_web),
        .dm_rdqs(sdram_dm),
        .odt(sdram_odt)
    );

  // END USER CODE (Do not remove this line)

endmodule


下にISimの結果を示す。
BitMapDispCont_115_120816.png

axi_s6_ddrx_0 のAXI4スレーブバスの信号が見えている。約57.3usec 後にuo_done_cal が1になってDDR2 SDRAMのキャリブレーションが終了し、ビットマップ・ディスプレイ・コントローラからAXI4 Readアクセスが開始されている。これは正常な動作だ。
ビットマップ・ディスプレイ・コントローラのエンジン部分 (bitmap_disp_engine.v) を見ても、正常に動作しているのがわかる。
BitMapDispCont_116_120816.png

シミュレーションでも正常だと、何が悪いのだろうか?そう言えば、MCBの外部入出力ピンのIOSTANDARDの設定をXPSのMIG設定にお任せしていて、自分で書いたUCF で SSTL18_II に設定してなかったと思うので、これを設定してみようと思う。
  1. 2012年08月16日 05:14 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog.fc2.com/tb.php/2226-a1cd7d76
この記事にトラックバックする(FC2ブログユーザー)