論理回路デザイン |
|
/* **************************** MODULE PREAMBLE ******************************** Copyright (c) 2012, ArchiTek This document constitutes confidential and proprietary information of ArchiTek. All rights reserved. // 基本クロックと4位相のクロックを生成する最上位モジュール*/ // ***************************** MODULE HEADER ********************************* `timescale 1ps / 1ps module test; // ************************ PARAMETER DECLARATIONS ***************************** parameter D = 1; parameter DCLK = 2500; parameter DCLK2 = DCLK/2; parameter DCLK4 = DCLK/4; // ************************** LOCAL DECLARATIONS ******************************* reg clk, clk_n; reg reset_n; reg ddr_clk_0, ddr_clk_90, ddr_clk_180, ddr_clk_270; // ****************************** 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 reset_n=0; #D reset_n=0; #(DCLK*3.5) reset_n=1; end // ----------------------------------------------------------------------------- initial begin ddr_clk_0 =0; #(DCLK4*0) forever begin #(DCLK2) ddr_clk_0 =~ddr_clk_0; end end initial begin ddr_clk_90 =0; #(DCLK4*1) forever begin #(DCLK2) ddr_clk_90 =~ddr_clk_90; end end initial begin ddr_clk_180=0; #(DCLK4*2) forever begin #(DCLK2) ddr_clk_180=~ddr_clk_180; end end initial begin ddr_clk_270=0; #(DCLK4*3) forever begin #(DCLK2) ddr_clk_270=~ddr_clk_270; end end // ----------------------------------------------------------------------------- top top_0 ( clk, clk_n, reset_n, ddr_clk_0, ddr_clk_90, ddr_clk_180, ddr_clk_270 ); // ************************** 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, reset_n, ddr_clk_0, ddr_clk_90, ddr_clk_180, ddr_clk_270 ); // ************************ PARAMETER DECLARATIONS ***************************** parameter ST = 10000; // Simulation interval // ***************************** I/O DECLARATIONS ****************************** input clk; input clk_n; input reset_n; input ddr_clk_0; input ddr_clk_90; input ddr_clk_180; input ddr_clk_270; // ************************** LOCAL DECLARATIONS ******************************* // 通常アクセスマスター信号 wire iReq; wire iGnt; wire iRxw; wire [31:0] iAddr; wire iWrStrb; wire iWrAck; wire [15:0] iWrData; wire [1:0] iWrMask; wire iRdStrb; wire iRdAck; wire [15:0] iRdData; // 割り込みアクセスマスター信号 wire pReq; wire pGnt; wire [31:0] pAddr; // sdcモジュールのDDR信号 wire sd_cs_n; wire sd_ras_n; wire sd_cas_n; wire sd_we_n; wire sd_cke = 1'b1; wire [2:0] sd_ba; wire [15:0] sd_addr; wire sd_odt = 1'b0; wire sd_reset_n = 1'b1; wire sd_wdvldt; wire sd_wdvldd; wire sd_wdvld = sd_wdvldt | sd_wdvldd; wire [15:0] sd_wd; wire [1:0] sd_wdqm; wire sd_rdvld; wire [15:0] sd_rd; // ACタイミングの設定 wire [7:0] reg_pACCW = 8'h18; wire [7:0] reg_pACCR = 8'h16; wire [7:0] reg_pCOM = 8'h4f; wire [4:0] reg_pFAW = 5'h12; wire [4:0] reg_pRRD = 5'h03; wire [4:0] reg_dTWR = 5'h0b; wire [4:0] reg_dTRW = 5'h06; wire [4:0] reg_dWL = 5'h07; wire [4:0] reg_dRL = 5'h08; // I/Oから見たDDR信号 wire ddr_cs_n; wire ddr_ras_n; wire ddr_cas_n; wire ddr_we_n; wire ddr_cke; wire [2:0] ddr_ba; wire [15:0] ddr_addr; wire ddr_odt; wire ddr_reset_n; wire [7:0] ddr_dq; wire ddr_dqm; wire ddr_dqs_p; wire ddr_dqs_n; wire ddr_rdqs_n; wire [7:0] ddr_din; wire [7:0] ddr_dout; wire [7:0] ddr_oe; wire ddr_dqsout; wire ddr_dqsin; wire ddr_dqs_poe; wire ddr_dqs_noe; wire ddr_dqs_pbus; wire ddr_clk_p; wire ddr_clk_n; // シミュレーション用変数 reg [1:0] rst; reg reset; reg [31:0] tsc; reg ts_req; wire ts_gnt; reg [31:0] ts_addr; reg ts_hold; wire ts_sdram; reg ts_sdc; reg ts_omit; reg omit; reg [31:0] addr; reg [31:0] data0; reg [31:0] data1; reg [31:0] reqCnt; reg [31:0] gntCnt; integer i; // ******************************** MODULE BODY ******************************** // ----------------------------------------------------------------------------- // Reset always @(posedge clk or negedge reset_n) if (!reset_n) rst <= #1 2'b11; else rst <= #1 {rst[0], 1'b0}; always @(posedge clk or negedge reset_n) if (!reset_n) reset <= #1 1'b1; else reset <= #1 rst[1]; // ----------------------------------------------------------------------------- // Time Count // タスクのカウンター always @(posedge clk or negedge reset_n) if (!reset_n) tsc <= #1 32'd0; else if (~&tsc & !ts_hold) tsc <= #1 tsc + 32'd1; always @(posedge clk or negedge reset_n) if (!reset_n) omit <= #1 1'b1; else omit <= #1 ts_omit; // DDR制御の非IDLE、終了判定に使用 assign ts_sdram = |sdc_0.cntl_0.state; // ----------------------------------------------------------------------------- // Parameter Access assign pReq = ts_req; assign pAddr = ts_addr; assign ts_gnt = pGnt; // ----------------------------------------------------------------------------- // Initialize Memory // DDRモデル内のメモリ値をインクリメンタルデータに初期化、DDRモデルが変われば変数名等変更が必要 always @(ts_sdc) if (ts_sdc) for (i=0; i<'h10_0000; i=i+1) begin // 8MB addr = 8*i; data0 = 2*i; data1 = 2*i + 1; sdram_0.memory[{addr[5:3], addr[27:13], addr[12:6]}] = {data1, data0}; end // ----------------------------------------------------------------------------- // Initialize Master // マスターの内のメモリ値をインクリメンタルデータに初期化 always @(ts_sdc) if (ts_sdc) for (i=0; i<'h10_0000; i=i+1) begin // 8MB addr = i; data0 = 2*i; data1 = 2*i + 1; master_0.mem[addr] = {data1, data0}; end // ----------------------------------------------------------------------------- // Master // 上位アドレスは変化しないようマスク(メモリ消費量や同じアドレスへのR/Wが重なる確率を上げるため) master #(32'h000ffff8, 1, 2) master_0 ( iReq, iGnt, iRxw, iAddr, iWrStrb, iWrAck, 1'b0, iWrData, iWrMask, iRdStrb, iRdAck, 1'b0, iRdData, omit, reset, clk ); // ----------------------------------------------------------------------------- // 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 (clk), .clk_n (clk_n), .reset_n (reset_n) ); // ----------------------------------------------------------------------------- // Statistics // 使用効率を出すため、リクエスト期間と受付期間を計測 always @(posedge clk) if (reset) begin reqCnt <= #1 32'd0; gntCnt <= #1 32'd0; end else if (!omit) begin reqCnt <= #1 reqCnt + 32'd1; gntCnt <= #1 gntCnt + (iReq & iGnt); end // ----------------------------------------------------------------------------- // Clock // ここから先はI/O部品 dobuf1 cbuf_0 ( .datain (clk), .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[1]), .dataout (ddr_dqm), .outclock (ddr_clk_270) ); // ----------------------------------------------------------------------------- // DQS diobuf1 sbuf_0 ( .datain (ddr_dqsout), .dataout (ddr_dqsin), .dataio (ddr_dqs_p), .dataio_b (ddr_dqs_n), .oe (ddr_dqs_poe), .oe_b (ddr_dqs_noe) ); // ----------------------------------------------------------------------------- // Data Lane // AlteraのALTDQ_DQSを模したモデル dlyd dlyd_0 ( .bidir_dq_input_data_in (ddr_din), .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[15:8]), .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), .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[15:8]), .bidir_dq_input_data_out_low (sd_rd[7:0]), .bidir_dq_oe_out (ddr_oe), .bidir_dq_output_data_out (ddr_dout), .dqs_bus_out (ddr_dqs_pbus), .dqs_oe_out (ddr_dqs_poe), .dqs_output_data_out (ddr_dqsout), .dqsn_oe_out (ddr_dqs_noe) ); iobuf8 dbuf_0 ( .datain (ddr_dout), .oe (ddr_oe), .dataio (ddr_dq), .dataout (ddr_din) ); // ----------------------------------------------------------------------------- // SDRAM // USEMがセットされていれば、付録のddr.vを使う // DDRモデルはMicronのddr.vを使うことを前提にしている(SpeedバージョンはSG25E) // Micronのddr.vは同じディレクトリにddr2_parameters.vhが必要 `ifdef USEM ddr_emu sdram_0 ( 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_rdqs_n, ddr_odt ); `else `define x8 `define sg25E ddr2 sdram_0 ( 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[14:0], ddr_dq, ddr_dqs_p, ddr_dqs_n, ddr_rdqs_n, ddr_odt ); `endif // **************************** FUNCTIONS and TASKS **************************** // DDRの初期化、マスターアクセスの許可(omit=0)、リフレッシュの挿入、終了処理を行う always @( tsc or ts_gnt or ts_sdram or omit or reqCnt or gntCnt ) begin ts_req = 1'b0; ts_addr = 32'h00000000; ts_hold = 1'b0; ts_sdc = 1'b0; ts_omit = omit; case (tsc) // ----------------------------------------------------------------------------- // Initialize SDRAM // ----------------------------------------------------------------------------- // DDR2: // AL=3, CL=5, WR=6, RL=AL+CL=8, RL=AL+CL=8, WL=RL-1=7 // tRP=5(12.5ns), tRRD=3(7.5ns), tRFC=79/28000(197.5ns/70us) // tRAS=16(40ns), tRC=22(55ns), tWTR=3(7.5ns), tFAW=18(45ns) // // FAW = tFAW = 18 // RRD = tRRD = 3 // CP = tRFC = 79 // APR = tRC = 22 // = tRAS+tRP = 21 // = 2+RL+BL/2+tRP = 19 // APW = tRC = 22 // = tRAS+tRP = 21 // = 2+WL+BL/2+tRP+WR = 24 // RCL = RL = 8 // WCL = WL = 7 // TRW = RL-WL+BL/2+1 = 6 // TWR = WL+BL/2-AL+tWTR = 11 // 1: begin $display(""); $display("********************"); $display("* Initialize Start *"); $display("********************"); end 10: Write (32'h04000200); // (Precharge-all) 11: Write (32'h00001000); // (EMRS1:0) 12: Write (32'h00002000); // (EMRS2:0) 13: Write (32'h00003000); // (EMRS3:0) 14: Write (32'h0b530000); // (MRS:WR=6,DLL=1,CL=5,BL=8) 15: Write (32'h04000200); // (Precharge-all) 16: Write (32'h00000400); // (Refresh) 17: Write (32'h00000400); // (Refresh) 18: Write (32'h0a530000); // (MRS:WR=6,DLL=0,CL=5,BL=8) 19: Write (32'h03981000); // (EMRS1:OCD=def,AL=3) 20: Write (32'h00181000); // (EMRS1:OCD=exit,AL=3) // ----------------------------------------------------------------------------- // SDRAM Initial Value Set // ----------------------------------------------------------------------------- 30: ts_sdc = 1'b1; // ----------------------------------------------------------------------------- // Master Access Start // ----------------------------------------------------------------------------- 50: begin $display(""); $display("****************"); $display("* Access Start *"); $display("****************"); ts_omit = 1'b0; end // ----------------------------------------------------------------------------- // Refresh Test // ----------------------------------------------------------------------------- // リフレッシュを要求(実際はタイマー起動すべき) 293: Write (32'h00000400); // (Refresh) // ----------------------------------------------------------------------------- // Finalize // ----------------------------------------------------------------------------- ST: ts_omit = 1'b1; ST+1: ts_hold = iReq | ts_sdram; ST+2: begin $display(""); $display("********************"); $display("* Access Terminate *"); $display("********************"); $display(""); // DDRの使用効率、4を掛けているのはバースト補正 $display("Density: %d/%d\t(%3d%% )", gntCnt<<2, reqCnt, 400*gntCnt/reqCnt); $display(""); $finish; end endcase end // ----------------------------------------------------------------------------- // Task // ----------------------------------------------------------------------------- task Write; input [31:0] Addr; begin ts_req = 1'b1; ts_addr = Addr; ts_hold = !ts_gnt; end endtask // ***************************************************************************** endmodule // *****************************************************************************
/* **************************** MODULE PREAMBLE ******************************** Copyright (c) 2011, 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; reg dataout_h, dataout_l; always @(posedge outclock) begin dataout_h <= #1 datain_h; dataout_l <= #1 datain_l; end assign dataout = outclock ? dataout_h : dataout_l; endmodule // ***************************************************************************** module obuf26 ( datain_h, datain_l, outclock, dataout ); input [25:0] datain_h, datain_l; output [25:0] dataout; input outclock; reg [25:0] dataout_h, dataout_l; always @(posedge outclock) begin dataout_h <= #1 datain_h; dataout_l <= #1 datain_l; end assign dataout = outclock ? dataout_h : dataout_l; endmodule // ***************************************************************************** module dobuf1 ( datain, dataout, dataout_b ); input datain; output dataout; output dataout_b; assign dataout = datain; assign dataout_b = ~datain; endmodule // ***************************************************************************** module iobuf8 ( datain, oe, dataio, dataout ); input [7:0] datain; output [7:0] dataout; inout [7:0] dataio; input [7:0] oe; assign dataout = dataio; assign dataio[7] = !oe[7] ? 1'bz : datain[7]; assign dataio[6] = !oe[6] ? 1'bz : datain[6]; assign dataio[5] = !oe[5] ? 1'bz : datain[5]; assign dataio[4] = !oe[4] ? 1'bz : datain[4]; assign dataio[3] = !oe[3] ? 1'bz : datain[3]; assign dataio[2] = !oe[2] ? 1'bz : datain[2]; assign dataio[1] = !oe[1] ? 1'bz : datain[1]; assign dataio[0] = !oe[0] ? 1'bz : datain[0]; 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; assign dataout = dataio; assign dataio = !oe ? 1'bz : datain; assign dataio_b = !oe ? 1'bz : ~datain; endmodule // *****************************************************************************
/* **************************** MODULE PREAMBLE ******************************** Copyright (c) 2011, 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 ); // *************************** 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 ******************************* reg [7:0] bidir_dq_input_data_out_high; reg [7:0] bidir_dq_input_data_out_low; reg [7:0] dq_data_latch; reg dqs_bus_out; reg dqsn_bus_out; reg dqs; reg en; reg [7:0] doea, doeb; reg [7:0] doa, dob; reg soea, soeb; reg soa, sob; reg dqs_output_data_out; // ****************************** MODULE BODY ********************************** // ----------------------------------------------------------------------------- // DQ Input always @(posedge dqs_bus_out) dq_data_latch <= #1 bidir_dq_input_data_in; always @(negedge dqs_bus_out) begin bidir_dq_input_data_out_high <= #1 bidir_dq_input_data_in; bidir_dq_input_data_out_low <= #1 dq_data_latch; end always @(negedge dqs or posedge dqs_enable_in) if (dqs_enable_in) en <= #1 1'b1; else en <= #1 1'b0; always @(dqs_input_data_in) dqs <= #2 dqs_input_data_in; always @(dqs or en) begin dqs_bus_out = en & dqs; dqsn_bus_out = ~en | ~dqs; end // ----------------------------------------------------------------------------- // 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 always @(posedge dq_output_reg_clk) if (dq_output_reg_clkena) doa <= #1 bidir_dq_output_data_in_high; always @(posedge dq_output_reg_clk) if (dq_output_reg_clkena) dob <= #1 bidir_dq_output_data_in_low; assign bidir_dq_output_data_out = dq_output_reg_clk ? doa : dob; // ----------------------------------------------------------------------------- // 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 always @(posedge dqs_output_reg_clk) if (dqs_output_reg_clkena) soa <= #1 dqs_output_data_in_high; always @(posedge dqs_output_reg_clk) if (dqs_output_reg_clkena) sob <= #1 dqs_output_data_in_low; always @(dqs_output_reg_clk or soa or sob) dqs_output_data_out <= dqs_output_reg_clk ? soa : sob; // ************************** FUNCTIONS and TASKS ****************************** endmodule // *****************************************************************************
/* **************************** MODULE PREAMBLE ******************************** Copyright (c) 2011, ArchiTek This document constitutes confidential and proprietary information of ArchiTek. All rights reserved. // x8bit限定 */ // ***************************** MODULE HEADER ********************************* module ddrse8 ( ck, ck_n, cke, cs_n, ras_n, cas_n, we_n, dm_rdqs, ba, addr, dq, dqs, dqs_n, rdqs_n, odt ); // ************************ PARAMETER DECLARATIONS ***************************** // DDR3なら1で動作、ただしreset_n端子は削ってある parameter SPD = 0; // *************************** I/O DECLARATIONS ******************************** input ck; input ck_n; input cke; input cs_n; input ras_n; input cas_n; input we_n; input dm_rdqs; input [2:0] ba; input [15:0] addr; inout [7:0] dq; inout dqs; inout dqs_n; output rdqs_n; input odt; // ************************** LOCAL DECLARATIONS ******************************* // Prepare reg [63:0] memory[0:33554431]; // 256MB reg reg_bl; // Burst Length 0:4 1:8 reg reg_bt; // Burst Type 0:Seq 1:Inter reg [3:0] reg_cl; // Cas Latency reg [3:0] reg_cwl; // Cas Write Latency reg [2:0] reg_al; // Additive Latency wire [3:0] al = reg_cl - reg_al; // Request reg [14:0] acta; reg [9:0] cola; reg [2:0] actba; reg rxw; reg [1:0] vpip[0:31]; reg [1:0] cpip[0:31]; reg [27:0] apip[0:31]; reg [1:0] ca; wire [3:0] cntl = {cs_n, ras_n, cas_n, we_n}; wire msr = (cntl == 4'b0000); wire pre = (cntl == 4'b0010); wire act = (cntl == 4'b0011); wire com = (cntl[3:1] == 3'b010); wire put = com | (|ca); // Write reg wr; reg [2:0] waddpt; reg [2:0] waddnt; reg [27:0] lwaddr; wire [4:0] wl = SPD ? (al + reg_cwl - 'h1) : (reg_al + reg_cl - 'h2); wire [1:0] wp = cpip[wl]; wire [27:0] waddr = apip[wl]; wire [2:0] waddp = {wp, 1'b0} + waddr[2:0]; wire [2:0] waddn = {wp, 1'b1} + waddr[2:0]; wire [63:0] wdata = memory[lwaddr[27:3]]; wire [63:0] wvldp = {{56{1'b0}}, {8{~dm_rdqs}}} << (waddpt * 8); wire [63:0] wvldn = {{56{1'b0}}, {8{~dm_rdqs}}} << (waddnt * 8); wire [63:0] wdp = ~wvldp & wdata | wvldp & {8{dq}}; wire [63:0] wdn = ~wvldn & wdata | wvldn & {8{dq}}; // Read reg rd; reg [2:0] raddpt; reg [2:0] raddnt; reg [63:0] lrdata; reg [7:0] qp, qn; reg doe; reg soe; wire [4:0] rl = SPD ? (al + reg_cl - 'h1) : (reg_al + reg_cl - 'h1); wire [1:0] rp = cpip[rl]; wire [27:0] raddr = apip[rl]; wire [2:0] raddp = {rp, 1'b0} + raddr[2:0]; wire [2:0] raddn = {rp, 1'b1} + raddr[2:0]; wire [63:0] rdata = memory[raddr[27:3]]; integer i; // ****************************** MODULE BODY ********************************** // ----------------------------------------------------------------------------- // Initialize initial begin reg_bl = 1'b1; reg_bt = 1'b0; reg_cl = 4'h3; reg_cwl = 4'h3; ca = 2'h0; for (i=0; i<32; i=i+1) begin vpip[i] = 2'h0; cpip[i] = 2'h0; apip[i] = 28'h0000000; end end // ----------------------------------------------------------------------------- // Request always @(posedge ck) // REG if (msr & (ba[1:0] == 2'b00)) begin reg_bl <= #1 SPD ? (addr[1:0] == 2'b00) : (addr[2:0] != 3'b010); reg_bt <= #1 addr[3]; reg_cl <= #1 addr[6:4] + (SPD ? 'h4 : 'h0); end always @(posedge ck) // REG if (msr & (ba[1:0] == 2'b01)) reg_al <= #1 SPD ? {1'b0, addr[4:3]} : addr[5:3]; always @(posedge ck) // REG if (msr & (ba[1:0] == 2'b10)) reg_cwl <= #1 addr[5:3] + 'h5; always @(posedge ck) // ACT if (act) begin acta <= #1 addr[14:0]; actba <= #1 ba; end always @(posedge ck) // COM if (com) begin cola <= #1 addr[9:0]; rxw <= #1 cntl[0]; end always @(posedge ck) // COM if (pre) ca <= #1 2'h0; else if (put) ca <= #1 (ca + 1'h1) & {reg_bl, 1'b1}; always @(posedge ck) // COM & charge if (pre) for (i=0; i<32; i=i+1) begin vpip[i] <= #1 2'h0; cpip[i] <= #1 2'h0; apip[i] <= #1 28'h0000000; end else begin for (i=31; i>0; i=i-1) begin vpip[i] <= #1 vpip[i-1]; cpip[i] <= #1 cpip[i-1]; apip[i] <= #1 apip[i-1]; end if (com) begin vpip[0] <= #1 {put, cntl[0]}; cpip[0] <= #1 ca; apip[0] <= #1 {actba, acta, addr[9:0]}; end else begin vpip[0] <= #1 {put, rxw}; cpip[0] <= #1 ca; end end // ----------------------------------------------------------------------------- // Write always @(negedge ck) begin wr <= #1 (vpip[wl] == 2'b10); waddpt <= #1 reg_bt ? ({wp, 1'b0} ^ waddr[2:0]) : {wp[1] ^ waddr[2], waddp[1:0]}; waddnt <= #1 reg_bt ? ({wp, 1'b1} ^ waddr[2:0]) : {wp[1] ^ waddr[2], waddn[1:0]}; lwaddr <= #1 waddr; end always @(posedge ck) if (wr) memory[lwaddr[27:3]] <= #1 wdp; always @(negedge ck) if (wr) memory[lwaddr[27:3]] <= #1 wdn; // ----------------------------------------------------------------------------- // Read always @(negedge ck) begin rd <= #1 (vpip[rl] == 2'b11); raddpt <= #1 reg_bt ? ({rp, 1'b0} ^ raddr[2:0]) : {rp[1] ^ raddr[2], raddp[1:0]}; raddnt <= #1 reg_bt ? ({rp, 1'b1} ^ raddr[2:0]) : {rp[1] ^ raddr[2], raddn[1:0]}; lrdata <= #1 rdata; end always @(posedge ck) if (rd) case (raddpt) 3'h0: qp <= #1 lrdata[7:0]; 3'h1: qp <= #1 lrdata[15:8]; 3'h2: qp <= #1 lrdata[23:16]; 3'h3: qp <= #1 lrdata[31:24]; 3'h4: qp <= #1 lrdata[39:32]; 3'h5: qp <= #1 lrdata[47:40]; 3'h6: qp <= #1 lrdata[55:48]; 3'h7: qp <= #1 lrdata[63:56]; endcase always @(negedge ck) if (rd) case (raddnt) 3'h0: qn <= #1 lrdata[7:0]; 3'h1: qn <= #1 lrdata[15:8]; 3'h2: qn <= #1 lrdata[23:16]; 3'h3: qn <= #1 lrdata[31:24]; 3'h4: qn <= #1 lrdata[39:32]; 3'h5: qn <= #1 lrdata[47:40]; 3'h6: qn <= #1 lrdata[55:48]; 3'h7: qn <= #1 lrdata[63:56]; endcase always @(posedge ck) doe <= #1 (vpip[rl] == 2'b11); always @(posedge ck) soe <= #1 (vpip[rl-1] == 2'b11) | (vpip[rl] == 2'b11); assign dq = doe ? (ck ? qp : qn) : 8'hzz; // 8'hzz if bi-directional buffer assign dqs = soe ? ~rdqs_n : 1'bz; // 2'bzz if bi-directional buffer assign dqs_n = soe ? rdqs_n : 1'bz; // 2'bzz if bi-directional buffer assign rdqs_n = ck_n | ~doe | ~rd; // ************************** FUNCTIONS and TASKS ****************************** endmodule // *****************************************************************************
回路デザイン > 設計例 [DDR制御(論理)] > テスト このページのTOP ▲