⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdr_tb.tf

📁 标准SDR SDRAM控制器参考设计
💻 TF
字号:
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Copyright (c) 2001 by Lattice Semiconductor Corporation
// --------------------------------------------------------------------
//
// Permission:
//
//   Lattice Semiconductor grants permission to use this code for use
//   in synthesis for any Lattice programmable logic product.  Other
//   use of this code, including the selling or duplication of any
//   portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL or Verilog source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Lattice Semiconductor provides no warranty
//   regarding the use or functionality of this code.
//
// --------------------------------------------------------------------
//           
//                     Lattice Semiconductor Corporation
//                     5555 NE Moore Court
//                     Hillsboro, OR 97214
//                     U.S.A
//
//                     TEL: 1-800-Lattice (USA and Canada)
//                          408-826-6000 (other locations)
//
//                     web: http://www.latticesemi.com/
//                     email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
//
// This is the test bench module of the SDR SDRAM controller reference
// design.  It is highly recommanded to download simulation modules
// from the SDRAM venders when you are working on the modification of
// the SDR SDRAM controller reference design.
//
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
//   Ver  :| Author            :| Mod. Date :| Changes Made:
//   V0.9 :| J.H.              :| 07/11/01  :| Pre-Release
// --------------------------------------------------------------------

`timescale 1ns / 100ps

module sdr_tb;

wire sys_R_Wn;      // read/write#
wire sys_ADSn;      // address strobe
wire sys_DLY_100US; // sdr power and clock stable for 100 us
wire sys_CLK;       // sdr clock
wire sys_RESET;     // reset signal
wire sys_REF_REQ;   // sdr auto-refresh request
wire sys_REF_ACK;   // sdr auto-refresh acknowledge
wire [23:1] sys_A;  // address bus
wire [15:0] sys_D;  // data bus
wire sys_D_VALID;   // data valid
wire sys_CYC_END;   // end of current cycle
wire sys_INIT_DONE; // initialization completed, ready for normal operation

wire [3:0] sdr_DQ;  // sdr data
wire [11:0] sdr_A;  // sdr address
wire [1:0] sdr_BA;  // sdr bank address
wire sdr_CKE;       // sdr clock enable
wire sdr_CSn;       // sdr chip select
wire sdr_RASn;      // sdr row address
wire sdr_CASn;      // sdr column select
wire sdr_WEn;       // sdr write enable
wire sdr_DQM;       // sdr write data mask

//---------------------------------------------------------------------
// modules

sdr_top UUT(
  .sys_R_Wn(sys_R_Wn),      // read/write#
  .sys_ADSn(sys_ADSn),      // address strobe
  .sys_DLY_100US(sys_DLY_100US), // sdr power and clock stable for 100 us
  .sys_CLK(sys_CLK),       // sdr clock
  .sys_RESET(sys_RESET),     // reset signal
  .sys_REF_REQ(sys_REF_REQ),   // sdr auto-refresh request
  .sys_REF_ACK(sys_REF_ACK),   // sdr auto-refresh acknowledge
  .sys_A(sys_A),         // address bus
  .sys_D(sys_D),         // data bus
  .sys_D_VALID(sys_D_VALID),   // data valid
  .sys_CYC_END(sys_CYC_END),   // end of current cycle
  .sys_INIT_DONE(sys_INIT_DONE), // initialization completed, ready for normal operation

  .sdr_DQ(sdr_DQ),        // sdr data
  .sdr_A(sdr_A),         // sdr address
  .sdr_BA(sdr_BA),        // sdr bank address
  .sdr_CKE(sdr_CKE),       // sdr clock enable
  .sdr_CSn(sdr_CSn),       // sdr chip select
  .sdr_RASn(sdr_RASn),      // sdr row address
  .sdr_CASn(sdr_CASn),      // sdr column select
  .sdr_WEn(sdr_WEn),       // sdr write enable
  .sdr_DQM(sdr_DQM)        // sdr write data mask
);

system STIMULUS(
  .sys_CLK(sys_CLK),
  .sys_RESET(sys_RESET),
  .sys_A(sys_A),
  .sys_ADSn(sys_ADSn),
  .sys_R_Wn(sys_R_Wn),
  .sys_D(sys_D),
  .sys_DLY_100US(sys_DLY_100US),
  .sys_REF_REQ(sys_REF_REQ),
  .sys_CYC_END(sys_CYC_END),
  .sys_INIT_DONE(sys_INIT_DONE)
);

// Module "mt48lc32m4a2" can be downloaded from Micro's web site.

//mt48lc32m4a2 SDR_SDRAM(
sdr SDR_SDRAM(
  sdr_DQ,
  sdr_A,
  sdr_BA,
  sys_CLK,
  sdr_CKE,
  sdr_CSn,
  sdr_RASn,
  sdr_CASn,
  sdr_WEn,
  sdr_DQM
);

endmodule 

module sdr (
  sdr_DQ,        // sdr data
  sdr_A,         // sdr address
  sdr_BA,        // sdr bank address
  sdr_CK,        // sdr clock
  sdr_CKE,       // sdr clock enable
  sdr_CSn,       // sdr chip select
  sdr_RASn,      // sdr row address
  sdr_CASn,      // sdr column select
  sdr_WEn,       // sdr write enable
  sdr_DQM        // sdr write data mask
);

//---------------------------------------------------------------------
// parameters of 8 Meg x 4 x 4 banks
//
parameter Num_Meg    =  8; //  8 Mb
parameter Data_Width =  4; //  4 bits
parameter Num_Bank   =  4; //  4 banks

parameter tAC = 5.4;
parameter tOH = 2.7;

parameter SDR_A_WIDTH  =  12; // 12 bits
parameter SDR_BA_WIDTH =  2;  // 2 bits (4 banks)

parameter MEG = 21'h100000;
parameter MEM_SIZE = Num_Meg * MEG * Num_Bank;
parameter ROW_WIDTH = 12;
parameter COL_WIDTH = (Data_Width ==  4) ? 11 :
                      (Data_Width ==  8) ? 10 :
                      (Data_Width == 16) ?  9 : 0;

//---------------------------------------------------------------------
// ports
//
input [SDR_A_WIDTH-1:0]  sdr_A;
input [SDR_BA_WIDTH-1:0] sdr_BA;
input                    sdr_CK;
input                    sdr_CKE;
input                    sdr_CSn;
input                    sdr_RASn;
input                    sdr_CASn;
input                    sdr_WEn;
input                    sdr_DQM;
inout [Data_Width-1:0]   sdr_DQ;

//---------------------------------------------------------------------
// registers
//
reg [Data_Width-1:0] Memory [0:MEM_SIZE-1];

reg [2:0]              casLatency;
reg [2:0]              burstLength;

reg [SDR_BA_WIDTH-1:0] bank;
reg [ROW_WIDTH-1:0]    row;
reg [COL_WIDTH-1:0]    column;

reg [3:0] counter;

reg [Data_Width-1:0]   dataOut;
reg enableSdrDQ;

reg write;
reg latency;
reg read;

//---------------------------------------------------------------------
// code 
//
initial begin
  casLatency = 0;
  burstLength = 0;
  bank = 0;
  row = 0;
  column = 0;
  counter = 0;
  dataOut = 0;
  enableSdrDQ = 0;
  write = 0;
  latency = 0;
  read = 0;
end

assign sdr_DQ =
         (Data_Width ==  4) ? (enableSdrDQ ? dataOut :  4'hz) :
         (Data_Width ==  8) ? (enableSdrDQ ? dataOut :  8'hzz) :
         (Data_Width == 16) ? (enableSdrDQ ? dataOut : 16'hzzzz) : 0;

always @(posedge sdr_CK)
  case ({sdr_CSn,sdr_RASn,sdr_CASn,sdr_WEn})
    4'b0000: begin
               $display($time,"ns : Load Mode Register %h",sdr_A);
               casLatency = sdr_A[6:4];
               burstLength = (sdr_A[2:0] == 3'b000) ? 1 :
                             (sdr_A[2:0] == 3'b001) ? 2 :
                             (sdr_A[2:0] == 3'b010) ? 4 :
                             (sdr_A[2:0] == 3'b011) ? 8 : 0;
               $display($time,
                     "ns : mode: CAS Latency=%d,Burst Length=%d",
                     casLatency, burstLength);
             end
    4'b0001: $display($time,"ns : Auto Refresh Command");
    4'b0010: $display($time,"ns : Precharge Command");
    4'b0011: begin
               $display($time,"ns : Activate Command");
               row = sdr_A;
             end
    4'b0100: begin
               $display($time,"ns : Write Command");
               column = (Data_Width ==  4) ? {sdr_A[11],sdr_A[9:0]} :
                        (Data_Width ==  8) ? {sdr_A[9:0]} :
                        (Data_Width == 16) ? {sdr_A[8:0]} : 0;
               bank = sdr_BA;
               write = 1;
               counter = burstLength;
               Memory[{row,column,bank}] = sdr_DQ;
               $display($time,
                     "ns :write: Bank=%d,Row=%d,Column=%d,Data=%d",
                     bank, row, column, sdr_DQ);
             end
    4'b0101: begin
               $display($time,"ns : Read Command");
               column = (Data_Width ==  4) ? {sdr_A[11],sdr_A[9:0]} :
                        (Data_Width ==  8) ? {sdr_A[9:0]} :
                        (Data_Width == 16) ? {sdr_A[8:0]} : 0;
               bank = sdr_BA;
               counter = {1'b0,casLatency} - 1;
               latency = 1;
             end
    4'b0110: $display($time,"ns : Burst Terminate");
    4'b0111: begin
//               $display($time,"ns : Nop Command");
               if ((write == 1) && (counter != 0))
                 begin
                   counter = counter - 1;
                   if (counter == 0) write = 0;
                   else
                     begin
                       column = column + 1;
                       Memory[{row,column,bank}] = sdr_DQ;
                       $display($time,
                         "ns :write: Bank=%d,Row=%d,Column=%d,Data=%d",
                         bank, row, column, sdr_DQ);
                     end
                 end
               else if ((read == 1) && (counter != 0))
                 begin
                   counter = counter - 1;
                   if (counter == 0)
                     begin
                       read = 0;
                       enableSdrDQ = #tOH 0;
                     end
                   else
                     begin
                       column = column + 1;
                       dataOut = #tAC Memory[{row,column,bank}];
                       $display($time,
                         "ns : read: Bank=%d,Row=%d,Column=%d,Data=%d",
                         bank, row, column, dataOut);
                     end
                 end
               else if ((latency == 1) && (counter != 0))
                 begin
                   counter = counter - 1;
                   if (counter == 0)
                     begin
                       latency = 0;
                       read = 1;
                       counter = burstLength;
                       dataOut = #tAC Memory[{row,column,bank}];
                       enableSdrDQ = 1;
                       $display($time,
                         "ns : read: Bank=%d,Row=%d,Column=%d,Data=%d",
                         bank, row, column, dataOut);
                     end
                 end
             end
  endcase
                
endmodule    
                                

module system(
  sys_CLK,
  sys_RESET,
  sys_A,
  sys_ADSn,
  sys_R_Wn,
  sys_D,
  sys_DLY_100US,
  sys_REF_REQ,
  sys_CYC_END,
  sys_INIT_DONE
);

`include "sdr_par.v"

//---------------------------------------------------------------------
// outputs & registers
//
output        sys_CLK;
output        sys_RESET;
output [23:1] sys_A;
output        sys_ADSn;
output        sys_R_Wn;
output [15:0] sys_D;
output        sys_DLY_100US;
output        sys_REF_REQ;

input         sys_CYC_END;
input         sys_INIT_DONE;

wire           sys_CLK;
reg           sys_CLK_int;
reg           sys_CLK_en;
reg           sys_RESET;
reg [23:1]    sys_A;
reg           sys_ADSn;
reg           sys_R_Wn;
reg [15:0]    sys_D;
reg           sys_DLY_100US;
reg           sys_REF_REQ;

wire          sys_CYC_END;

//---------------------------------------------------------------------
// parameters -- change to whatever you like
//
parameter clock_time = 100;
parameter reset_time = 1000;

parameter sys_CLK_period = tCK;

//---------------------------------------------------------------------
// tasks
//
task write;
    input [23:1] addr;
    input [15:0] data;
  begin
    sys_A = addr;
    sys_ADSn = 0;
    sys_R_Wn = 0;
    #sys_CLK_period;
    sys_ADSn = 1;
    sys_D = data;
    #(sys_CLK_period * (NUM_CLK_WRITE + NUM_CLK_WAIT + 4));
    sys_D = 16'hzzzz;
    sys_R_Wn = 1;
    sys_A = 24'hzzzzzz;
  end
endtask

task read;
    input [23:1] addr;
  begin
    sys_A = addr;
    sys_ADSn = 0;
    sys_R_Wn = 1;
    #sys_CLK_period;
    sys_ADSn = 1;
    #(sys_CLK_period * (NUM_CLK_CL + NUM_CLK_READ + 3));
    sys_R_Wn = 1;
    sys_A = 24'hzzzzzz;
  end
endtask

//---------------------------------------------------------------------
// code
//
initial begin
    sys_R_Wn    <= #1 1'b1;
    sys_ADSn    <= #1 1'b1;
    sys_DLY_100US   <= #1 1'b0;
    sys_REF_REQ <= #1 1'b0;
    sys_CLK_int <= #1 1'b0;
    sys_RESET   <= #1 1'b1;
    sys_A       <= #1 24'hFFFFFF;
    sys_D       <= #1 16'hzzzz;
    sys_CLK_en  <= #1 1'b0;
    #clock_time;
    sys_CLK_en  <= #1 1'b1;
    #reset_time;
    @(posedge sys_CLK);
    $display($time,"ns : Coming Out Of Reset");
    sys_RESET    <= #1 1'b0;
    #100000;
    sys_DLY_100US    <= #1 1'b1;
    @(posedge sys_INIT_DONE);
    #500;
    @(negedge sys_CLK);
    write(23'h000000, 16'h1234);
    write(23'h000200, 16'h5678);
    write(23'h000400, 16'h9ABC);
    write(23'h000600, 16'hDEF0);
    read(23'h000000);
    read(23'h000200);
    read(23'h000400);
    read(23'h000600);
    $stop;
end
    
always 
    #(sys_CLK_period/2) sys_CLK_int <= ~sys_CLK_int;
    
assign sys_CLK = sys_CLK_en & sys_CLK_int;

endmodule    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -