Spartan-6 LX9 MicroBoardを使ったLPDDR SDRAMのハードマクロ実装(その4)
MIGが生成したuser_designを使って、MCBラッパーと分散メモリのインスタンシエートをしているわけですが、ふと、違和感を感じました。user_designのトップファイルのモジュール宣言。
module mymig # ( //(中略) ) ( inout [C3_NUM_DQ_PINS-1:0] mcb3_dram_dq, output [C3_MEM_ADDR_WIDTH-1:0] mcb3_dram_a, output [C3_MEM_BANKADDR_WIDTH-1:0] mcb3_dram_ba, output mcb3_dram_cke, output mcb3_dram_ras_n, output mcb3_dram_cas_n, output mcb3_dram_we_n, output mcb3_dram_dm, inout mcb3_dram_udqs, inout mcb3_rzq, output mcb3_dram_udm, input c3_sys_clk, input c3_sys_rst_i, output c3_calib_done, output c3_clk0, output c3_rst0, inout mcb3_dram_dqs, output mcb3_dram_ck, output mcb3_dram_ck_n, input c3_p0_cmd_clk, input c3_p0_cmd_en, input [2:0] c3_p0_cmd_instr, input [5:0] c3_p0_cmd_bl, input [29:0] c3_p0_cmd_byte_addr, output c3_p0_cmd_empty, output c3_p0_cmd_full, input c3_p0_wr_clk, input c3_p0_wr_en, input [C3_P0_MASK_SIZE - 1:0] c3_p0_wr_mask, input [C3_P0_DATA_PORT_SIZE - 1:0] c3_p0_wr_data, output c3_p0_wr_full, output c3_p0_wr_empty, output [6:0] c3_p0_wr_count, output c3_p0_wr_underrun, output c3_p0_wr_error, input c3_p0_rd_clk, input c3_p0_rd_en, output [C3_P0_DATA_PORT_SIZE - 1:0] c3_p0_rd_data, output c3_p0_rd_full, output c3_p0_rd_empty, output [6:0] c3_p0_rd_count, output c3_p0_rd_overflow, output c3_p0_rd_error );
example_designをずっと参考にしていたので、このモジュールをガシガシ改造していかなくてはならないのかなと思い込んでいましたが、ここでどうやら違うということをようやく理解しました。
よくよく考えると、このモジュールを改造したらLPDDR以外のDDR2 SDRAMなどのMCBラッパーを生成したときに使いまわせなくなっちゃいますねorz
ufcファイルの階層が一段階深くなってしまうので、そこを注意しないといけません。もし、ucfのこのモジュール無いよ、というエラーが出たらそれが原因です。
そして、トップファイルtop.vはこんな構成にしました。(長いので注意)
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Lynx-EyED WORKS and it's Klavier Craft // Engineer: lynxeyed_atsu // // Create Date: 11:13:45 10/08/2011 // Design Name: // Module Name: top // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// (* X_CORE_INFO = "mig_v3_8_lpddr_lpddr_s6, Coregen 13.2" , CORE_GENERATION_INFO = "lpddr_lpddr_s6,mig_v3_8,{component_name=mymig, C3_MEM_INTERFACE_TYPE=LPDDR, C3_CLK_PERIOD=5000, C3_MEMORY_PART=mt46h32m16xxxx-5, C3_MEMORY_DEVICE_WIDTH=16, C3_PA_SR=FULL, C3_OUTPUT_DRV=FULL, C3_PORT_CONFIG=Two 32-bit bi-directional and four 32-bit unidirectional ports, C3_MEM_ADDR_ORDER=ROW_BANK_COLUMN, C3_PORT_ENABLE=Port0, C3_INPUT_PIN_TERMINATION=EXTERN_TERM, C3_DATA_TERMINATION=25 Ohms, C3_CLKFBOUT_MULT_F=4, C3_CLKOUT_DIVIDE=2, C3_DEBUG_PORT=0, C3_INPUT_CLK_TYPE=Single-Ended, LANGUAGE=Verilog, SYNTHESIS_TOOL=Foundation_ISE, NO_OF_CONTROLLERS=1}" *) module top #( parameter C3_P0_MASK_SIZE = 4, parameter C3_P0_DATA_PORT_SIZE = 32, parameter C3_P1_MASK_SIZE = 4, parameter C3_P1_DATA_PORT_SIZE = 32, parameter DEBUG_EN = 0, // # = 1, Enable debug signals/controls, // = 0, Disable debug signals/controls. parameter C3_MEMCLK_PERIOD = 15000, // Memory data transfer clock period parameter C3_CALIB_SOFT_IP = "TRUE", // # = TRUE, Enables the soft calibration logic, // # = FALSE, Disables the soft calibration logic. parameter C3_SIMULATION = "FALSE", // # = TRUE, Simulating the design. Useful to reduce the simulation time, // # = FALSE, Implementing the design. parameter C3_RST_ACT_LOW = 0, // # = 1 for active low reset, // # = 0 for active high reset. parameter C3_INPUT_CLK_TYPE = "SINGLE_ENDED", // input clock type DIFFERENTIAL or SINGLE_ENDED parameter C3_MEM_ADDR_ORDER = "ROW_BANK_COLUMN", // The order in which user address is provided to the memory controller, // ROW_BANK_COLUMN or BANK_ROW_COLUMN parameter C3_NUM_DQ_PINS = 16, // External memory data width parameter C3_MEM_ADDR_WIDTH = 13, // External memory address width parameter C3_MEM_BANKADDR_WIDTH = 2 // External memory bank address width ) ( output [3:0] GPIO_LED, //Spartan-6 LX9 MB上のLED output calib_done, output error, inout [C3_NUM_DQ_PINS-1:0] mcb3_dram_dq, output [C3_MEM_ADDR_WIDTH-1:0] mcb3_dram_a, output [C3_MEM_BANKADDR_WIDTH-1:0] mcb3_dram_ba, output mcb3_dram_cke, output mcb3_dram_ras_n, output mcb3_dram_cas_n, output mcb3_dram_we_n, output mcb3_dram_dm, inout mcb3_dram_udqs, inout mcb3_rzq, output mcb3_dram_udm, input c3_sys_clk, input c3_sys_rst_i, inout mcb3_dram_dqs, output mcb3_dram_ck, output mcb3_dram_ck_n ); wire mainclk; // topモジュールで使うメインクロック。実態はMCBから供給されるc3_clk0 wire user_wire_cmd_en; wire[2:0] user_wire_cmd_instr; wire[5:0] user_wire_cmd_bl; wire[29:0] user_wire_cmd_byte_addr; wire user_wire_cmd_empty; wire user_wire_cmd_full; wire user_wire_wr_en; wire[C3_P0_MASK_SIZE - 1:0] user_wire_wr_mask; wire[C3_P0_DATA_PORT_SIZE - 1:0] user_wire_wr_data; wire user_wire_wr_full; wire user_wire_wr_empty; wire[6:0] user_wire_wr_count; wire user_wire_wr_underrun; wire user_wire_wr_error; wire user_wire_rd_en; wire[C3_P0_DATA_PORT_SIZE - 1:0] user_wire_rd_data; wire user_wire_rd_full; wire user_wire_rd_empty; wire[6:0] user_wire_rd_count; wire user_wire_rd_overflow; wire user_wire_rd_error; // MCB module instantiation mymig #( .C3_P0_MASK_SIZE (C3_P0_MASK_SIZE), .C3_P0_DATA_PORT_SIZE (C3_P0_DATA_PORT_SIZE), .C3_P1_MASK_SIZE (C3_P1_MASK_SIZE), .C3_P1_DATA_PORT_SIZE (C3_P1_DATA_PORT_SIZE), .DEBUG_EN (DEBUG_EN), .C3_MEMCLK_PERIOD (C3_MEMCLK_PERIOD), .C3_CALIB_SOFT_IP (C3_CALIB_SOFT_IP), .C3_SIMULATION (C3_SIMULATION), .C3_RST_ACT_LOW (C3_RST_ACT_LOW), .C3_INPUT_CLK_TYPE (C3_INPUT_CLK_TYPE), .C3_MEM_ADDR_ORDER (C3_MEM_ADDR_ORDER), .C3_NUM_DQ_PINS (C3_NUM_DQ_PINS), .C3_MEM_ADDR_WIDTH (C3_MEM_ADDR_WIDTH), .C3_MEM_BANKADDR_WIDTH (C3_MEM_BANKADDR_WIDTH) ) lpddr_mig( .mcb3_dram_dq (mcb3_dram_dq), .mcb3_dram_a (mcb3_dram_a), .mcb3_dram_ba (mcb3_dram_ba), .mcb3_dram_cke (mcb3_dram_cke), .mcb3_dram_ras_n (mcb3_dram_ras_n), .mcb3_dram_cas_n (mcb3_dram_cas_n), .mcb3_dram_we_n (mcb3_dram_we_n), .mcb3_dram_dm (mcb3_dram_dm), .mcb3_dram_udqs (mcb3_dram_udqs), .mcb3_rzq (mcb3_rzq), .mcb3_dram_udm (mcb3_dram_udm), .c3_sys_clk (c3_sys_clk), .c3_sys_rst_i (c3_sys_rst_i), .c3_calib_done (c3_calib_done), .c3_clk0 (mainclk), .c3_rst0 (c3_rst0), .mcb3_dram_dqs (mcb3_dram_dqs), .mcb3_dram_ck (mcb3_dram_ck), .mcb3_dram_ck_n (mcb3_dram_ck_n), //ここからMCBラッパーで取り扱う信号 .c3_p0_cmd_clk (mainclk), .c3_p0_cmd_en (user_wire_cmd_en), .c3_p0_cmd_instr (user_wire_cmd_instr), .c3_p0_cmd_bl (user_wire_cmd_bl), .c3_p0_cmd_byte_addr (user_wire_cmd_byte_addr), .c3_p0_cmd_empty (user_wire_cmd_empty), .c3_p0_cmd_full (user_wire_cmd_full), .c3_p0_wr_clk (mainclk), .c3_p0_wr_en (user_wire_wr_en), .c3_p0_wr_mask (user_wire_wr_mask), .c3_p0_wr_data (user_wire_wr_data), .c3_p0_wr_full (user_wire_wr_full), .c3_p0_wr_empty (user_wire_wr_empty), .c3_p0_wr_count (user_wire_wr_count), .c3_p0_wr_underrun (user_wire_wr_underrun), .c3_p0_wr_error (user_wire_wr_error), .c3_p0_rd_clk (mainclk), .c3_p0_rd_en (user_wire_rd_en), .c3_p0_rd_data (user_wire_rd_data), .c3_p0_rd_full (user_wire_rd_full), .c3_p0_rd_empty (user_wire_rd_empty), .c3_p0_rd_count (user_wire_rd_count), .c3_p0_rd_overflow (user_wire_rd_overflow), .c3_p0_rd_error (user_wire_rd_error) ); reg user_reg_cmd_en; reg[2:0] user_reg_cmd_instr; reg[5:0] user_reg_cmd_bl; reg[29:0] user_reg_cmd_byte_addr; reg user_reg_wr_clk; reg user_reg_wr_en; reg[C3_P0_MASK_SIZE - 1:0] user_reg_wr_mask; reg[C3_P0_DATA_PORT_SIZE - 1:0] user_reg_wr_data; reg user_reg_rd_en; assign user_wire_cmd_en = user_reg_cmd_en; assign user_wire_cmd_instr = user_reg_cmd_instr; assign user_wire_cmd_bl = user_reg_cmd_bl; assign user_wire_cmd_byte_addr = user_reg_cmd_byte_addr; assign user_wire_wr_clk = user_reg_wr_clk; assign user_wire_wr_en = user_reg_wr_en; assign user_wire_wr_mask = user_reg_wr_mask; assign user_wire_wr_data = user_reg_wr_data; assign user_wire_rd_en = user_reg_rd_en; //^^^^^^^^^^^^^^^^ // ここからステートマシンもろもろを記述 //^^^^^^^^^^^^^^^^ endmodule