/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
`timescale 1ps / 1ps
module test;
// ************************ PARAMETER DECLARATIONS *****************************
parameter D = 1;
// 基本クロックの周期は今回の動作周波数175MHzに設定する
parameter DCLK = 5714;
parameter DCLK2 = DCLK/2;
// ************************** LOCAL DECLARATIONS *******************************
reg clk, clk_n;
reg resetin;
// ****************************** MODULE BODY **********************************
// -----------------------------------------------------------------------------
// 差動クロック信号入力(無限ループ)
initial begin clk=0; forever begin #(DCLK2) clk=~clk; end end
initial begin clk_n=1; forever begin #(DCLK2) clk_n=~clk_n; end end
// -----------------------------------------------------------------------------
// 基板上のプッシュボタンによるリセット信号入力(正論理)
initial begin resetin=1; #D resetin=1; #(DCLK*3.5) resetin=0; end
// -----------------------------------------------------------------------------
// topモジュールのI/0は、クロック/リセット入力、DDR3 I/F、LED出力のみ
top top_0 (
clk, clk_n, resetin, ddr_clk_p, ddr_clk_n,
ddr_cke, ddr_cs_n, ddr_ras_n, ddr_cas_n,
ddr_we_n, ddr_dqm, ddr_ba, ddr_addr,
ddr_dq, ddr_dqs_p, ddr_dqs_n,
ddr_odt, ddr_reset_n,
led_init, led_exec, led_err
);
// ************************** FUNCTIONS and TASKS ******************************
endmodule
// *****************************************************************************
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
module top (
clk, clk_n, resetin, ddr_clk_p, ddr_clk_n,
ddr_cke, ddr_cs_n, ddr_ras_n, ddr_cas_n,
ddr_we_n, ddr_dqm, ddr_ba, ddr_addr,
ddr_dq, ddr_dqs_p, ddr_dqs_n,
ddr_odt, ddr_reset_n,
led_init, led_exec, led_err
);
// ************************ PARAMETER DECLARATIONS *****************************
parameter REGWD = 34; // Register width
parameter REFWAIT = 41; // Refresh wait
parameter REFACS = 42; // Refresh access
// ***************************** I/O DECLARATIONS ******************************
input clk;
input clk_n;
input resetin;
output ddr_clk_p;
output ddr_clk_n;
output ddr_cke;
output ddr_cs_n;
output ddr_ras_n;
output ddr_cas_n;
output ddr_we_n;
output [1:0] ddr_dqm;
output [2:0] ddr_ba;
output [15:0] ddr_addr;
inout [15:0] ddr_dq;
inout [1:0] ddr_dqs_p;
inout [1:0] ddr_dqs_n;
// input [1:0] ddr_rdqs_n;
output ddr_odt;
output ddr_reset_n;
output led_init; // LED for initialize
output [5:0] led_exec; // LED for execution
output led_err; // LED for diff error
// ************************** LOCAL DECLARATIONS *******************************
wire reset_n;
// PLL IPコアからのクロック信号
wire ddr_clk_0;
wire ddr_clk_180;
wire ddr_clk_270;
// 通常アクセスマスター信号(内部バス32bit対応)
wire iReq;
wire iGnt;
wire iRxw;
wire [31:0] iAddr;
wire iWrStrb;
wire iWrAck;
wire [31:0] iWrData;
wire [3:0] iWrMask;
wire iRdStrb;
wire iRdAck;
wire [31:0] iRdData;
// 割り込みアクセスマスター信号
wire pReq;
wire pGnt;
wire [31:0] pAddr;
// sdcモジュールのDDR信号(内部バス32bit対応)
// reset_n信号、cke信号は初期化制御のためそれぞれpAddr[3]、pAddr[4]を割り当て
wire sd_cs_n;
wire sd_ras_n;
wire sd_cas_n;
wire sd_we_n;
wire sd_cke = ~pAddr[4];
wire [2:0] sd_ba;
wire [15:0] sd_addr;
wire sd_odt = 1'b0;
wire sd_reset_n = ~pAddr[3];
wire sd_wdvldt;
wire sd_wdvldd;
wire sd_wdvld = sd_wdvldt | sd_wdvldd;
wire [31:0] sd_wd;
wire [3:0] sd_wdqm;
wire sd_rdvld;
wire [31:0] sd_rd;
// ACタイミングの設定
wire [7:0] reg_pACCW = 8'h19;
wire [7:0] reg_pACCR = 8'h14;
wire [7:0] reg_pCOM = 8'h2c;
wire [4:0] reg_pFAW = 5'h14;
wire [4:0] reg_pRRD = 5'h04;
wire [4:0] reg_dTWR = 5'h0d;
wire [4:0] reg_dTRW = 5'h05;
wire [4:0] reg_dWL = 5'h08;
wire [4:0] reg_dRL = 5'h08;
reg [1:0] rst;
reg reset;
// sdcモジュールとI/Oバッファ間のDDR信号(16bitバス対応)
wire [15:0] ddr_din;
wire [15:0] ddr_dout;
wire [15:0] ddr_oe;
wire [1:0] ddr_dqsout;
wire [1:0] ddr_dqsin;
wire [1:0] ddr_dqs_poe;
wire [1:0] ddr_dqs_noe;
wire [1:0] ddr_dqs_pbus;
// ステート実行用信号
wire ts_req;
wire ts_gnt;
wire [31:0] ts_addr;
wire ts_omit;
reg omit;
wire [5:0] exec;
// ******************************** MODULE BODY ********************************
IBUF IBUF_rst_i0 (.I (resetin), .O (rst_i));
// Generate the internal reset - it is asserted whenever the reset pin
// is asserted, or the DCM is not locked
assign reset_n = !rst_i & clock_locked;
// Core Generatorで作成したクロック供給用PLL IPコア
// Clock source
clk_core clk_core_i0
(// Clock in ports
.CLK_IN1_P(clk), // IN
.CLK_IN1_N(clk_n), // IN
// Clock out ports
.CLK_OUT1(ddr_clk_0), // OUT
.CLK_OUT2(ddr_clk_180), // OUT
.CLK_OUT3(ddr_clk_270), // OUT
// Status and control signals
.RESET(rst_i),// IN
.LOCKED(clock_locked)); // OUT
// -----------------------------------------------------------------------------
// Reset
always @(posedge ddr_clk_0 or negedge reset_n)
if (!reset_n)
rst <= #1 2'b11;
else
rst <= #1 {rst[0], 1'b0};
always @(posedge ddr_clk_0 or negedge reset_n)
if (!reset_n)
reset <= #1 1'b1;
else
reset <= #1 rst[1];
// -----------------------------------------------------------------------------
// Initialize Term
// DDR初期化中、通常アクセス可能状態の判定に使用
always @(posedge ddr_clk_0 or negedge reset_n)
if (!reset_n)
omit <= #1 1'b1;
else
omit <= #1 ts_omit;
// -----------------------------------------------------------------------------
// Parameter Access
assign pReq = ts_req;
assign pAddr = ts_addr;
assign ts_gnt = pGnt;
// -----------------------------------------------------------------------------
// Master
// パラメータは8Meg×16×8banksの1Gbit DDR3デバイスアクセスに合わせる
master #(32'h03fffff0, 2, 5) master_0 (
iReq, iGnt, iRxw, iAddr,
iWrStrb, iWrAck, 1'b0, iWrData, iWrMask,
iRdStrb, iRdAck, 1'b0, iRdData,
omit, exec, error,
reset, ddr_clk_0
);
// -----------------------------------------------------------------------------
// Body
// RowアドレスはiAddrの13bit目からマッピング
sdc #(13) sdc_0 (
.iReq (iReq),
.iGnt (iGnt),
.iRxw (iRxw),
.iAddr (iAddr),
.iWrAck (iWrAck),
.iWrData (iWrData),
.iWrMask (iWrMask),
.iRdAck (iRdAck),
.iRdData (iRdData),
.pReq (pReq),
.pGnt (pGnt),
.pAddr (pAddr),
.cs_n (sd_cs_n),
.ras_n (sd_ras_n),
.cas_n (sd_cas_n),
.we_n (sd_we_n),
.addr (sd_addr),
.ba (sd_ba),
.wdvld (sd_wdvldt),
.wdvldd (sd_wdvldd),
.wd (sd_wd),
.wdqm (sd_wdqm),
.rdvld (sd_rdvld),
.rd (sd_rd),
.reg_pACCW (reg_pACCW),
.reg_pACCR (reg_pACCR),
.reg_pCOM (reg_pCOM),
.reg_pFAW (reg_pFAW),
.reg_pRRD (reg_pRRD),
.reg_dTWR (reg_dTWR),
.reg_dTRW (reg_dTRW),
.reg_dWL (reg_dWL),
.reg_dRL (reg_dRL),
.clk (ddr_clk_0),
.clk_n (ddr_clk_180),
.reset_n (reset_n)
);
// -----------------------------------------------------------------------------
// Clock
// ここから先はI/O部品
// デバイスのデータバス幅を16bitに対応
dobuf1 cbuf_0 (
.datain (ddr_clk_0),
.dataout (ddr_clk_p),
.dataout_b (ddr_clk_n)
);
// -----------------------------------------------------------------------------
// Command Buffer
obuf26 abuf_0 (
.datain_h ({sd_cs_n, sd_ras_n, sd_cas_n, sd_we_n,
sd_cke, sd_ba, sd_addr,
sd_odt, sd_reset_n
}),
.datain_l ({sd_cs_n, sd_ras_n, sd_cas_n, sd_we_n,
sd_cke, sd_ba, sd_addr,
sd_odt, sd_reset_n
}),
.dataout ({ddr_cs_n, ddr_ras_n, ddr_cas_n, ddr_we_n,
ddr_cke, ddr_ba, ddr_addr,
ddr_odt, ddr_reset_n
}),
.outclock (ddr_clk_180)
);
// -----------------------------------------------------------------------------
// DQM
obuf1 qbuf_0 (
.datain_h (sd_wdqm[0]),
.datain_l (sd_wdqm[2]),
.dataout (ddr_dqm[0]),
.outclock (ddr_clk_270)
);
obuf1 qbuf_1 (
.datain_h (sd_wdqm[1]),
.datain_l (sd_wdqm[3]),
.dataout (ddr_dqm[1]),
.outclock (ddr_clk_270)
);
// -----------------------------------------------------------------------------
// DQS
diobuf1 sbuf_0 (
.datain (ddr_dqsout[0]),
.dataout (ddr_dqsin[0]),
.dataio (ddr_dqs_p[0]),
.dataio_b (ddr_dqs_n[0]),
.oe (ddr_dqs_poe[0]),
.oe_b (ddr_dqs_noe[0])
);
diobuf1 sbuf_1 (
.datain (ddr_dqsout[1]),
.dataout (ddr_dqsin[1]),
.dataio (ddr_dqs_p[1]),
.dataio_b (ddr_dqs_n[1]),
.oe (ddr_dqs_poe[1]),
.oe_b (ddr_dqs_noe[1])
);
// -----------------------------------------------------------------------------
// Data Lane
// Xilinx Vertex-6 SelectIOリソースを使用したPHYモデル
dlyd dlyd_0 (
.bidir_dq_input_data_in (ddr_din[7:0]),
.bidir_dq_oe_in ({8{sd_wdvld}}),
.bidir_dq_output_data_in_high (sd_wd[7:0]),
.bidir_dq_output_data_in_low (sd_wd[23:16]),
.dll_delayctrlin (6'h00),
.dq_output_reg_clk (ddr_clk_270),
.dq_output_reg_clkena (1'b1),
.dqs_enable_in (sd_rdvld),
.dqs_input_data_in (ddr_dqsin[0]),
.dqs_oe_in (sd_wdvld),
.dqs_output_data_in_high (sd_wdvldd),
.dqs_output_data_in_low (1'b0),
.dqs_output_reg_clk (ddr_clk_0),
.dqs_output_reg_clkena (1'b1),
.dqsn_oe_in (sd_wdvld),
.bidir_dq_input_data_out_high (sd_rd[23:16]),
.bidir_dq_input_data_out_low (sd_rd[7:0]),
.bidir_dq_oe_out (ddr_oe[7:0]),
.bidir_dq_output_data_out (ddr_dout[7:0]),
.dqs_bus_out (ddr_dqs_pbus[0]),
.dqs_oe_out (ddr_dqs_poe[0]),
.dqs_output_data_out (ddr_dqsout[0]),
.dqsn_oe_out (ddr_dqs_noe[0])
);
dlyd dlyd_1 (
.bidir_dq_input_data_in (ddr_din[15:8]),
.bidir_dq_oe_in ({8{sd_wdvld}}),
.bidir_dq_output_data_in_high (sd_wd[15:8]),
.bidir_dq_output_data_in_low (sd_wd[31:24]),
.dll_delayctrlin (6'h00),
.dq_output_reg_clk (ddr_clk_270),
.dq_output_reg_clkena (1'b1),
.dqs_enable_in (sd_rdvld),
.dqs_input_data_in (ddr_dqsin[1]),
.dqs_oe_in (sd_wdvld),
.dqs_output_data_in_high (sd_wdvldd),
.dqs_output_data_in_low (1'b0),
.dqs_output_reg_clk (ddr_clk_0),
.dqs_output_reg_clkena (1'b1),
.dqsn_oe_in (sd_wdvld),
.bidir_dq_input_data_out_high (sd_rd[31:24]),
.bidir_dq_input_data_out_low (sd_rd[15:8]),
.bidir_dq_oe_out (ddr_oe[15:8]),
.bidir_dq_output_data_out (ddr_dout[15:8]),
.dqs_bus_out (ddr_dqs_pbus[1]),
.dqs_oe_out (ddr_dqs_poe[1]),
.dqs_output_data_out (ddr_dqsout[1]),
.dqsn_oe_out (ddr_dqs_noe[1])
);
iobuf8 dbuf_0 (
.datain (ddr_dout[7:0]),
.oe (ddr_oe[7:0]),
.dataio (ddr_dq[7:0]),
.dataout (ddr_din[7:0])
);
iobuf8 dbuf_1 (
.datain (ddr_dout[15:8]),
.oe (ddr_oe[15:8]),
.dataio (ddr_dq[15:8]),
.dataout (ddr_din[15:8])
);
// SelectIOリソースでIODELAYを使用する際に必要なコントロールブロック
IDELAYCTRL idelayctrl_inst (
.REFCLK (), // Default 200MHz
.RST (reset),
.RDY ()
);
// 実際の実行動作を司るステートマシンとその変数
// プログラムカウンタpc[7:0]の値により実行状態を管理する
// **************************** STATE PARAMETER ********************************
parameter IDLE = 2'b00;
parameter WAIT = 2'b01;
parameter REGACS = 2'b10;
// **************************** FUNCTIONS and TASKS ****************************
reg [1:0] state;
reg [15:0] count;
reg [7:0] pc;
wire [REGWD-1:0] current;
wire [REGWD-1:0] next;
// **************************** STATE DESCRIPTION ******************************
always @(posedge ddr_clk_0 or negedge reset_n)
if (!reset_n) begin
count <= #1 16'h0000;
pc <= #1 8'h00;
state <= #1 IDLE;
end
else
case (state)
IDLE: if (current[32])
state <= #1 REGACS;
else state <= #1 WAIT;
WAIT: if (!next[32] && (count == current[15:0])) begin
count <= #1 16'h0000;
pc <= #1 pc + 8'd1;
state <= #1 WAIT;
end else
if (next[32] && (count == current[15:0])) begin
count <= #1 16'h0000;
pc <= #1 pc + 8'd1;
state <= #1 REGACS;
end else
begin count <= #1 count + 16'd1;
state <= #1 WAIT;
end
REGACS: if (ts_gnt && (current[33:32] == 2'b11)) begin
pc <= #1 pc - 8'd1;
state <= #1 WAIT;
end else
if (ts_gnt && !next[32]) begin
pc <= #1 pc + 8'd1;
state <= #1 WAIT;
end else
if (ts_gnt && next[32]) begin
pc <= #1 pc + 8'd1;
state <= #1 REGACS;
end else state <= #1 REGACS;
endcase
assign current = Write( pc );
assign next = Write( pc + 8'd1 );
assign ts_req = (state == REGACS);
assign ts_addr = (state == REGACS) ? current[31:0] : 32'h00000000;
assign ts_omit = ~(pc == REFWAIT || pc == REFACS);
// 初期化完了、実行動作中、エラーを表示するLED出力
OBUF OBUF_led_i0 (.I (~ts_omit), .O(led_init));
OBUF OBUF_led_i1 (.I (exec[0]), .O(led_exec[0]));
OBUF OBUF_led_i2 (.I (exec[1]), .O(led_exec[1]));
OBUF OBUF_led_i3 (.I (exec[2]), .O(led_exec[2]));
OBUF OBUF_led_i4 (.I (exec[3]), .O(led_exec[3]));
OBUF OBUF_led_i5 (.I (exec[4]), .O(led_exec[4]));
OBUF OBUF_led_i6 (.I (exec[5]), .O(led_exec[5]));
OBUF OBUF_led_i7 (.I (error), .O(led_err));
// -----------------------------------------------------------------------------
// Initialize SDRAM
// -----------------------------------------------------------------------------
// DDR3:
// AL=3, CL=5, WR=6, RL=AL+CL=8, WL=AL+CWL=8
// tRP=5(12.5ns), tRRD=4(10ns), tRFC=44/28000(110ns/70us)
// tRAS=15(37.5ns), tRC=20(50ns), tWTR=4(10ns), tFAW=20(50ns)
//
// FAW = tFAW = 20
// RRD = tRRD = 4
// CP = tRFC = 44
// APR = tRC = 20
// = tRAS+tRP = 20
// = 2+RL+BL/2+tRP = 19
// APW = tRC = 20
// = tRAS+tRP = 20
// = 2+WL+BL/2+tRP+WR = 25
// RCL = RL = 8
// WCL = WL = 8
// TRW = RL-WL+BL/2+1 = 5
// TWR = WL+BL/2-AL+tWTR = 13
//
// 電源投入直後から実際の処理を実行するファクション
// 初期化終了後はリフレッシュとリフレッシュウェイトを繰り返す
// -----------------------------------------------------------------------------
// Function
// -----------------------------------------------------------------------------
function [REGWD-1:0] Write;
input [7:0] pc;
case (pc)
// reset_nとckeの制御でμオーダーの待機時間は暫定的に短く設定
0: Write = 34'h000000000;
1: Write = 34'h100000719;
2: Write = 34'h100000719;
3: Write = 34'h100000719;
4: Write = 34'h100000719;
5: Write = 34'h100000719;
6: Write = 34'h100000719;
7: Write = 34'h100000719;
8: Write = 34'h100000719;
9: Write = 34'h100000719;
10: Write = 34'h100000719;
11: Write = 34'h100000719;
12: Write = 34'h100000719;
13: Write = 34'h100000711; // (reset inactive)
14: Write = 34'h100000711;
15: Write = 34'h100000711;
16: Write = 34'h100000711;
17: Write = 34'h100000711;
18: Write = 34'h100000711;
19: Write = 34'h100000711;
20: Write = 34'h100000711;
21: Write = 34'h100000711;
22: Write = 34'h100000711;
23: Write = 34'h100000711;
24: Write = 34'h100000711;
25: Write = 34'h100000711;
26: Write = 34'h100000711;
27: Write = 34'h100000711;
28: Write = 34'h100000711;
29: Write = 34'h100000711;
30: Write = 34'h100000711;
31: Write = 34'h100000711;
32: Write = 34'h100000711;
33: Write = 34'h000000060; // (wait)
34: Write = 34'h100002000; // (MRS:CWL=5)
35: Write = 34'h100003000; // (MR3:0)
36: Write = 34'h100101000; // (MRS:AL=CL-2)
37: Write = 34'h115100000; // (MRS:DLL on,WR=6,DLL reset,CL=5,BL=8)
38: Write = 34'h104000300; // (ZQCL CMD)
39: Write = 34'h000000200; // (wait)
40: Write = 34'h100000400; // (Refresh)
// リフレッシュウェイト(周期)は実時間で70us必要なので、動作周波数に合わせて変更が必要
// 400MHz時28000なので、28000×175/400=12250
REFWAIT: Write = 34'h000002fda; // (Refresh period on 175MHz)
REFACS: Write = 34'h300000400; // (Refresh)
default: Write = 34'h000000000;
endcase
endfunction
// *****************************************************************************
endmodule
// *****************************************************************************
I/Oバッファ
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// *****************************************************************************
module obuf1 (
datain_h, datain_l, outclock, dataout
);
input datain_h;
input datain_l;
output dataout;
input outclock;
// ****************************** MODULE BODY **********************************
ODDR # (
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC")
)
u_dqm_out (
.Q (dataout),
.C (outclock),
.CE (1'b1),
.D1 (datain_h),
.D2 (datain_l),
.R (1'b0),
.S (1'b0)
);
endmodule
// *****************************************************************************
module obuf26 (
datain_h, datain_l, outclock, dataout
);
input [25:0] datain_h, datain_l;
output [25:0] dataout;
input outclock;
// ****************************** MODULE BODY **********************************
ODDR # (
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC")
)
u_ddr_ctrl_out[25:0] (
.Q (dataout),
.C (outclock),
.CE (1'b1),
.D1 (datain_h),
.D2 (datain_l),
.R (1'b0),
.S (1'b0)
);
endmodule
// *****************************************************************************
module dobuf1 (
datain, dataout, dataout_b
);
input datain;
output dataout;
output dataout_b;
// ****************************** MODULE BODY **********************************
ODDR # (
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC")
)
u_clk_p_out (
.Q (dataout),
.C (datain),
.CE (1'b1),
.D1 (1'b1),
.D2 (1'b0),
.R (1'b0),
.S (1'b0)
);
ODDR # (
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC")
)
u_clk_p_out (
.Q (dataout_b),
.C (datain),
.CE (1'b1),
.D1 (1'b0),
.D2 (1'b1),
.R (1'b0),
.S (1'b0)
);
endmodule
// *****************************************************************************
module iobuf8 (
datain, oe, dataio, dataout
);
input [7:0] datain;
output [7:0] dataout;
inout [7:0] dataio;
input [7:0] oe;
// ****************************** MODULE BODY **********************************
IOBUF u_iobuf_dq[7:0] (
.I (datain),
.T (~oe),
.IO (dataio),
.O (dataout)
);
endmodule
// *****************************************************************************
module diobuf1 (
datain, dataout, dataio, dataio_b, oe, oe_b
);
input datain;
output dataout;
inout dataio;
inout dataio_b;
input oe;
input oe_b;
// ****************************** MODULE BODY **********************************
IOBUFDS u_iobuf_dqs (
.I (datain),
.O (dataout),
.IO (dataio),
.IOB (dataio_b),
.T (~oe)
);
endmodule
// *****************************************************************************
PHYモデル(RTL)
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
module dlyd (
bidir_dq_input_data_in, bidir_dq_oe_in,
bidir_dq_output_data_in_high, bidir_dq_output_data_in_low,
dll_delayctrlin,
dq_output_reg_clk, dq_output_reg_clkena,
dqs_enable_in, dqs_input_data_in, dqs_oe_in,
dqs_output_data_in_high, dqs_output_data_in_low,
dqs_output_reg_clk, dqs_output_reg_clkena,
dqsn_oe_in,
bidir_dq_input_data_out_high, bidir_dq_input_data_out_low,
bidir_dq_oe_out, bidir_dq_output_data_out,
dqs_bus_out, dqs_oe_out, dqs_output_data_out, dqsn_oe_out
);
// **************************** DELAY PARAMETER ********************************
// リードデータをサンプリングするためのDQS入力遅延パラメータ(1Tap 78ps)
parameter DQSDELAY = 21; // DQS INPUT DELAY(TAP:0-31)
// *************************** I/O DECLARATIONS ********************************
input [7:0] bidir_dq_input_data_in;
input [7:0] bidir_dq_oe_in;
input [7:0] bidir_dq_output_data_in_high;
input [7:0] bidir_dq_output_data_in_low;
input [5:0] dll_delayctrlin;
input dq_output_reg_clk;
input dq_output_reg_clkena;
input dqs_enable_in;
input dqs_input_data_in;
input dqs_oe_in;
input dqs_output_data_in_high;
input dqs_output_data_in_low;
input dqs_output_reg_clk;
input dqs_output_reg_clkena;
input dqsn_oe_in;
output [7:0] bidir_dq_input_data_out_high;
output [7:0] bidir_dq_input_data_out_low;
output [7:0] bidir_dq_oe_out;
output [7:0] bidir_dq_output_data_out;
output dqs_bus_out;
output dqs_oe_out;
output dqs_output_data_out;
output dqsn_oe_out;
// ************************** LOCAL DECLARATIONS *******************************
wire [7:0] bidir_dq_input_data_out_high;
reg [7:0] bidir_dq_input_data_out_low;
wire [7:0] dq_data_latch;
wire dqs_bus_out;
wire dqs_input_delay;
reg dqs;
reg en;
reg [7:0] doea, doeb;
reg soea, soeb;
// reg dqs_output_data_out;
// ****************************** MODULE BODY **********************************
// -----------------------------------------------------------------------------
// DQ Input
IDDR # (
.DDR_CLK_EDGE ("OPPOSITE_EDGE"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.SRTYPE ("ASYNC")
)
u_ddr_dq_in[7:0] (
.Q1 (dq_data_latch),
.Q2 (bidir_dq_input_data_out_high),
.C (dqs_bus_out),
.CE (1'b1),
.D (bidir_dq_input_data_in),
.R (1'b0),
.S (1'b0)
);
always @(negedge dqs_bus_out)
bidir_dq_input_data_out_low
<= #1 dq_data_latch;
always @(negedge dqs or posedge dqs_enable_in)
if (dqs_enable_in)
en <= #1 1'b1;
else
en <= #1 1'b0;
// DQS入力遅延制御部、遅延値はパラメータ設定
IODELAYE1 # (
.IDELAY_TYPE ("FIXED"),
.IDELAY_VALUE (DQSDELAY),
)
iodelay_inst (
.C (1'b0),
.CE (1'b0),
.DATAIN (1'b0),
.IDATAIN (dqs_input_data_in),
.INC (1'b0),
.ODATAIN (1'b0),
.RST (1'b0),
.T (1'b1),
.DATAOUT (dqs_input_delay)
);
always @(dqs_input_delay)
dqs <= #2 dqs_input_delay;
BUFGCE u_bufgce_dqs (
.O (dqs_bus_out),
.CE (en),
.I (dqs)
);
// -----------------------------------------------------------------------------
// DQ OE
always @(posedge dq_output_reg_clk)
if (dq_output_reg_clkena)
doea <= #1 bidir_dq_oe_in;
always @(negedge dq_output_reg_clk)
if (dq_output_reg_clkena)
doeb <= #1 doea;
assign bidir_dq_oe_out = {8{doea & doeb}};
// -----------------------------------------------------------------------------
// DQ Out
ODDR # (
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC")
)
u_ddr_dq_out[7:0] (
.Q (bidir_dq_output_data_out),
.C (dq_output_reg_clk),
.CE (dq_output_reg_clkena),
.D1 (bidir_dq_output_data_in_high),
.D2 (bidir_dq_output_data_in_low),
.R (1'b0),
.S (1'b0)
);
// -----------------------------------------------------------------------------
// DQS OE
always @(posedge dqs_output_reg_clk)
if (dqs_output_reg_clkena)
soea <= #1 dqs_oe_in;
always @(negedge dqs_output_reg_clk)
if (dqs_output_reg_clkena)
soeb <= #1 soea;
assign dqs_oe_out = soea;
assign dqsn_oe_out = soea;
// -----------------------------------------------------------------------------
// DQS Out
ODDR # (
.DDR_CLK_EDGE ("SAME_EDGE"),
.INIT (1'b0),
.SRTYPE ("ASYNC")
)
u_ddr_dqs_out (
.Q (dqs_output_data_out),
.C (dqs_output_reg_clk),
.CE (dqs_output_reg_clkena),
.D1 (dqs_output_data_in_high),
.D2 (dqs_output_data_in_low),
.R (1'b0),
.S (1'b0)
);
// ************************** FUNCTIONS and TASKS ******************************
endmodule
// *****************************************************************************
回路デザイン > 設計例 [DDR制御(実装)] > 動作検証2 次のページ(タイミング調整) このページのTOP ▲