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

📄 ddr_data.v

📁 DDR RAM控制器的VHDL源码, 实现平台是Lattice FPGA
💻 V
字号:
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> 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 data path module of the SDR SDRAM controller reference
// design.
//
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
//   Ver  :| Author            :| Mod. Date :| Changes Made:
//   V0.1 :| Nagaraj Chekka    :| 07/23/03  :| Pre-Release
// --------------------------------------------------------------------

`timescale 1ns / 1ps

module ddr_data(
                clk,
                clk2x,
                reset_n,
                sys_dataout,
                sys_dataout_en,
                sys_datain,
                sys_dmsel,
                cstate,
                wren,
                sys_rdyn,
                dqin,
                dqout,
                dqout_en,
                dqsout,
                dqsout_en,
                dqm_out
                );

`include "ddr_par.v"

//---- INPUTS
input                       clk;             // Clkx from HPPLL
input 			    clk2x;           // Clk2x from HPPLL
input 			    reset_n;         // System reset
input [3:0] 		    cstate;          // Control state machine output
input 			    wren;            // Write enable signal 
input [DSIZE-1:0] 	    sys_datain;      // System data in
input [DSIZE/8-1:0] 	    sys_dmsel;       // System data mask select.
input [DSIZE/2-1:0] 	    dqin;            // DDR data in (read data)

//---- OUTPUTS
output [DSIZE/2-1:0] 	    dqout_en;        // DDR output enables
output [DSIZE/2-1:0] 	    dqout;           // DDR output (write data)
output [DSIZE/16-1:0] 	    dqsout_en;       // DDR output enables
output [DSIZE/16-1:0] 	    dqsout;          // DDR output strobe
output 			    sys_rdyn;        // Ready signal to the system

output [DSIZE-1:0] 	    sys_dataout    /*synthesis dout="" */ ;
output [DSIZE-1:0] 	    sys_dataout_en /*synthesis syn_preserve=1 */ /*synthesis dout="" */ ;
output [DSIZE/16-1:0] 	    dqm_out;         // Data mask output to DDR

//---- REGISTERS
reg [DSIZE/2-1:0] 	    dqout_en      /*synthesis syn_preserve=1 */ /*synthesis dout="" */ ;
reg [DSIZE/2-1:0] 	    dqout         /*synthesis dout="" */ ; 
reg [DSIZE/16-1:0] 	    dqsout_en     /*synthesis syn_preserve=1 */ /*synthesis dout="" */ ; 
reg [DSIZE/16-1:0] 	    dqsout        /*synthesis dout="" */ ; 
reg 			    sys_rdyn;
reg [DSIZE-1:0] 	    sys_dataout_en /*synthesis syn_preserve=1 */ /*synthesis dout="" */;
reg [DSIZE/16-1:0] 	    dqm_out       /*synthesis dout="" */ ; // DDR SDRAM Data Mask signals

//--- Internal Registers
// Read path registers
reg [DSIZE/2-1:0] 	    dqin_2x_sync_reg /*synthesis din="" */;
reg [DSIZE/2-1:0] 	    dqin_x_reg;
reg [DSIZE/2-1:0] 	    dqin_xn_reg;
reg [DSIZE/2-1:0] 	    dqin_xnx_reg;
reg [DSIZE/2-1:0] 	    dqin_reg_l  /*synthesis dout="" */ ;
reg [DSIZE/2-1:0] 	    dqin_reg_h  /*synthesis dout="" */ ;
// Write path registers
reg [DSIZE/2+DSIZE/16-1:0]  dqout_and_dqsout_en /*synthesis syn_preserve=1 */;
reg [DSIZE/2-1:0] 	    dqout_reg;
reg [DSIZE/16-1:0] 	    dqm_outreg;
reg [DSIZE/2-1:0] 	    datain_regl /*synthesis din="" */;
reg [DSIZE/16-1:0] 	    dmsel_regl  /*synthesis din="" */;
reg [DSIZE-1:0] 	    datain_nx ;
reg [DSIZE/8-1:0] 	    dmsel_nx  ;
reg 			    dqsout_reg;
reg 			    select_lower_half;
reg 			    write_rdy_d1;
reg 			    write_rdy_d2;
reg 			    write_rdy_d3;
reg 			    read_rdy;
reg 			    read_rdy_d;
reg 			    write_rdy;
reg 			    wren_d2x;
reg 			    wren_dx;
reg [DSIZE/16-1:0] 	    dqsout_en_nx;


//--- WIRES
wire [DSIZE-1:0] 	    sys_dataout;


//====================================================================
//  Read Cycle Data Path
//====================================================================

// Latching the incoming DDR data

always @(posedge clk2x or negedge reset_n)begin
   if (reset_n == 1'b0)
     dqin_2x_sync_reg <= {DSIZE/2{1'b0}};
   else
     dqin_2x_sync_reg <= dqin;
end

// +ve edge clk
always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      dqin_x_reg      <= {DSIZE/2{1'b0}};
      dqin_xnx_reg    <= {DSIZE/2{1'b0}};
   end
   else begin
      dqin_x_reg     <= dqin_2x_sync_reg;
      
      // dqin_xnx_reg will be used only for
      // CAS latency = 2.5. 
      if (MR_CAS_Latency == Latency_25) 
        dqin_xnx_reg <= dqin_xn_reg;     
   end
end

// -ve edge clk 
always @(negedge clk  or negedge reset_n) begin
   if (reset_n == 1'b0)
     dqin_xn_reg <= {DSIZE/2{1'b0}};
   else
     dqin_xn_reg <= dqin_2x_sync_reg;
end


// Tranfering the data +ve clk

always @(posedge clk  or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      dqin_reg_l <= {DSIZE/2{1'b0}};
      dqin_reg_h <= {DSIZE/2{1'b0}};
   end else begin
      if (MR_CAS_Latency == Latency_25) begin
         dqin_reg_h  <= dqin_x_reg;
         dqin_reg_l  <= dqin_xnx_reg;
      end else begin
         dqin_reg_h  <= dqin_xn_reg;
         dqin_reg_l  <= dqin_x_reg;
      end
   end
end

assign sys_dataout = {dqin_reg_h, dqin_reg_l};


//====================================================================
//  Write Cycle Data Path
//====================================================================


// Generation of dqout_en and dqsout_en for DDRRAM


// Assert the DDR output and DDR strobe output enables during
// the c_WRITEA, c_wdata and c_tDAL states

always @(posedge clk or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     dqout_and_dqsout_en <= {DSIZE/2+DSIZE/16 {1'b0}};
  end else begin
     case (cstate)
       c_WRITEA,c_wdata,c_tDAL : begin
	  // For XPGA
	  // dqout_and_dqsout_en <= {DSIZE/2+DSIZE/16 {1'b1}};

	  // For ORCA
	  dqout_and_dqsout_en <= {DSIZE/2+DSIZE/16 {1'b0}};
       end
       default: begin
	  // For XPGA
	  // dqout_and_dqsout_en <= {DSIZE/2+DSIZE/16 {1'b0}};

	  // For ORCA
	  dqout_and_dqsout_en <= {DSIZE/2+DSIZE/16 {1'b1}};
       end
     endcase     
  end
end 
      
// Both dq_out, and dqout_en should be clocked by the
// same clock and the same edge (+ve clk2x). This is required 
// otherwise PAR tool will not place output flops in PIC.

always @(posedge clk2x or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     dqout_en     <= {DSIZE/2 {1'b0}};       
  end else begin
     dqout_en     <= dqout_and_dqsout_en[DSIZE/2-1:0];
  end
end

always @(negedge clk or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     dqsout_en_nx    <= {DSIZE/16 {1'b0}};
  end else begin
     dqsout_en_nx    <= dqout_and_dqsout_en[DSIZE/2+DSIZE/16-1: DSIZE/2];
  end
end
     
always @(negedge clk2x or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     dqsout_en    <= {DSIZE/16 {1'b0}};
  end else begin
     dqsout_en    <= dqsout_en_nx;
  end
end
     
// Generation of dqsout
always @(posedge clk2x or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     wren_dx <= 1'b0;
  end else begin
     wren_dx <= wren_d2x ? ~wren_dx : 1'b0;
  end
end

// Note that dqsout and dqsout_en are clocked
// with the same clock and the same edge (-ve clk2x)

always @(negedge clk2x or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     dqsout_reg    <= 1'b0; 
     dqsout        <= {DSIZE/16{1'b0}};
  end else begin
     dqsout_reg    <= wren_dx;
     dqsout        <= dqsout_reg;
  end
end


// Generation of dqout

// Latch the system data on +ve clk

always @(negedge clk or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     datain_nx <=  {DSIZE{1'b0}};
     dmsel_nx  <=  {DSIZE/8{1'b0}};
  end else begin
     datain_nx <=  sys_datain[DSIZE-1:0];
     dmsel_nx  <=  sys_dmsel[DSIZE/8-1:0];
  end
end

// dqout_reg has two clocks (of clk2x) from sys_datain and datain_nx.
// Similarly for dqm_out.
// This is essential to meet the desired frequency.

always @(posedge clk2x or negedge reset_n) begin
  if (reset_n == 1'b0) begin
     wren_d2x             <= 1'b0;
     select_lower_half    <= 1'b0;
     dqout_reg            <= {DSIZE/2 {1'b0}};
     dqm_outreg           <= {DSIZE/16 {1'b0}};
     dqout                <= {DSIZE/2 {1'b0}};
     dqm_out              <= {DSIZE/16{1'b0}};
  end else begin
     wren_d2x             <= wren;
     select_lower_half    <= wren_d2x ? ~select_lower_half : 1'b0;
     dqout_reg            <= select_lower_half ? datain_nx[DSIZE-1:DSIZE/2]  : sys_datain[DSIZE/2-1:0];
     dqm_outreg           <= select_lower_half ? dmsel_nx[DSIZE/8-1:DSIZE/16]: sys_dmsel[DSIZE/16-1:0];
     dqout                <= dqout_reg;
     dqm_out              <= dqm_outreg;
  end
end
        
//====================================================================
// Generation of sys_rdyn. When sys_rdyn goes low
// data transfer takes place. Applies to read and write
//====================================================================

always @(posedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      sys_rdyn        <= 1'b1;
      write_rdy_d1    <= 1'b0;
      write_rdy_d2    <= 1'b0;
      write_rdy_d3    <= 1'b0;
      read_rdy        <= 1'b0;
      read_rdy_d      <= 1'b0;
   end else begin
      
      // Generate for read and write cycles, during data transfer
      // This will be useful to directly attach to processors
      // Also during refresh time, if master requests read/write cycles.
      write_rdy_d1       <= write_rdy;
      write_rdy_d2       <= write_rdy_d1;
      write_rdy_d3       <= write_rdy_d2;

      read_rdy          <= (cstate == c_rdata) ? 1'b1 : 1'b0;
      read_rdy_d        <= (read_rdy || (cstate == c_rdata) ) ? 1'b1: 1'b0;
      
      if (NUM_CLK_WRITE == 1)    // For burst length 2
        sys_rdyn         <= !(write_rdy    | read_rdy);

      if (NUM_CLK_WRITE == 2)    // For burst length 4
        sys_rdyn         <= !(write_rdy | write_rdy_d1 | read_rdy);

      if (NUM_CLK_WRITE == 4)    // For burst length 8
        sys_rdyn       <= !(write_rdy | write_rdy_d1 | write_rdy_d2  | write_rdy_d3 | read_rdy);
   end
end



// Generation of sys_dataout_en

always @(negedge clk or negedge reset_n) begin
   if (reset_n == 1'b0) begin
      sys_dataout_en  <= {DSIZE{1'b0}};
   end else begin
      sys_dataout_en  <= read_rdy_d  ? {DSIZE {1'b0}} : {DSIZE {1'b1}};
   end
end

// Generation of write_rdy (combinational signal)

always @ (cstate ) begin
   case (cstate)
     c_WRITEA: begin
        write_rdy = 1'b1;
     end
     default: begin
        write_rdy = 1'b0;
     end
   endcase
end

endmodule

⌨️ 快捷键说明

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