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

📄 top_func.v

📁 DDR(双速率)SDRAM控制器参考设计
💻 V
📖 第 1 页 / 共 3 页
字号:
   end      //add IO buffers to get out of FPGA   OBUF ddr_ba0  (.O(ddr_ba[0]),  .I(ddr_ba_o_P1[0] ));   OBUF ddr_ba1  (.O(ddr_ba[1]),  .I(ddr_ba_o_P1[1] ));      wire [11:0] ddr_ad_o_dly = ddr_ad_o_P1;      // ddr_addr_io_12.v   OBUF  ddr_ad0  (.O(ddr_ad[0]),  .I(ddr_ad_o_dly[0] ));	OBUF  ddr_ad1  (.O(ddr_ad[1]),  .I(ddr_ad_o_dly[1] ));	OBUF  ddr_ad2  (.O(ddr_ad[2]),  .I(ddr_ad_o_dly[2] ));	OBUF  ddr_ad3  (.O(ddr_ad[3]),  .I(ddr_ad_o_dly[3] ));	OBUF  ddr_ad4  (.O(ddr_ad[4]),  .I(ddr_ad_o_dly[4] ));	OBUF  ddr_ad5  (.O(ddr_ad[5]),  .I(ddr_ad_o_dly[5] ));	OBUF  ddr_ad6  (.O(ddr_ad[6]),  .I(ddr_ad_o_dly[6] ));	OBUF  ddr_ad7  (.O(ddr_ad[7]),  .I(ddr_ad_o_dly[7] ));	OBUF  ddr_ad8  (.O(ddr_ad[8]),  .I(ddr_ad_o_dly[8] ));	OBUF  ddr_ad9  (.O(ddr_ad[9]),  .I(ddr_ad_o_dly[9] ));	OBUF  ddr_ad10 (.O(ddr_ad[10]), .I(ddr_ad_o_dly[10]));	OBUF  ddr_ad11 (.O(ddr_ad[11]), .I(ddr_ad_o_dly[11]));	//`include "ddr_addr_io_12.v"endmodule // addr_latchmodule brst_cntr ( /*AUTOARG*/   // Outputs   brst_end,    // Inputs   clk,    ld_brst   );      input clk, ld_brst;   output brst_end;   reg 	  b_1, brst_end;      always @ (posedge clk)    begin      b_1 <= ~ld_brst;      brst_end <= b_1;   end   endmodule // brst_cntrmodule clk_dlls(/*AUTOARG*/   // Outputs   ddr_clk_out,    ddr_clk180_out,    fpga_clk2x_out,    fpga_clk_out,    fpga_clk270_out,//   fpga_clk90_out,   dlls_locked_out,    fpga_lac_clk_out,    fpga_lac_clk90_out,    // Inputs   sys_clk_in,    sys_clk_fb_in,    reset_in   );   input sys_clk_in, sys_clk_fb_in, reset_in;   output ddr_clk_out, ddr_clk180_out;   output fpga_clk2x_out, fpga_clk_out, fpga_clk270_out;   output dlls_locked_out;   output fpga_lac_clk_out, fpga_lac_clk90_out;  //Logic Accessible Clock      IBUFG  ibufg_sys_clk    (.I(sys_clk_in), .O(sys_clk));   IBUFG  ibufg_sys_clk_fb (.I(sys_clk_fb_in), .O(sys_clk_fb));      CLKDLL dll_ext			     (.CLKIN(sys_clk), 				  .CLKFB(sys_clk_fb), 				  .RST(1'b0), 			     .CLK0(ddr_clk_out_o), 				  .CLK90(), 				  .CLK180(), 				  .CLK270(), 			     .CLK2X(), 				  .CLKDV(), 				  .LOCKED(dll_ext_locked));   //dll_int gets CLKIN from ddr_clk   //since ddr_clk is not stable until dll_ext achieve lock,    //we need to hold dll_int in reset untill dll_ext_lock goes high   wire   dll_int_reset = ~dll_ext_locked;      CLKDLL dll_int		     (.CLKIN(sys_clk_fb), 			  .CLKFB(fpga_clk_out), 			  .RST(dll_int_reset), 		     .CLK0(fpga_clk_out_o), 			  .CLK90(), 			  .CLK180(), 			  .CLK270(fpga_clk270_out_o), 		     .CLK2X(fpga_clk2x_out_o), 			  .CLKDV(), 			  .LOCKED(dll_int_locked));     OBUF  obuf_ddr_clk_out (.I(ddr_clk_out_o), .O(ddr_clk_out));   OBUF  obuf_ddr_clk180_out (.I(~ddr_clk_out_o), .O(ddr_clk180_out));   BUFG bufg_clk2x  (.I(fpga_clk2x_out_o), .O(fpga_clk2x_out));   BUFG bufg_clk    (.I(fpga_clk_out_o),.O(fpga_clk_out));   BUFG bufg_clk270 (.I(fpga_clk270_out_o), .O(fpga_clk270_out)); //  BUFG bufg_clk90 (.I(fpga_clk90_out_o), .O(fpga_clk90_out));      assign dlls_locked_out = dll_int_locked & dll_ext_locked;    //In data_path module, we need to use clk to select b/t lower and    // higher bits of system data and use clk2x to generate double data output   //However, the clk signal cannot drive non clock CLB pins in Virtex, so   //we need to generate Logic Accessible Clock signals   //generate Logic Accessible Clock signals   wire #6 sys_clk_dly = sys_clk; //simulate routing delay   FD LAC1 (.D(~sys_clk_dly), .C(fpga_clk2x_out), .Q(lac_clk1));   FD LAC2 (.D(~lac_clk1), .C(fpga_clk2x_out), .Q(lac_clk2));   FD LAC3 (.D(~lac_clk2), .C(fpga_clk2x_out), .Q(fpga_lac_clk_out));     //BUFG bufg_lac_clk ( .I(fpga_lac_clk_out_o), .O(fpga_lac_clk_out));  // BUFG bufg_lac_clk90 ( .I(fpga_lac_clk90_out_o), .O(fpga_lac_clk90_out));   FD LAC4 (.D(sys_clk_dly), .C(~fpga_clk2x_out), .Q(lac_clk90_1));   FD LAC5 (.D(~lac_clk90_1), .C(~fpga_clk2x_out), .Q(lac_clk90_2));   FD LAC6 (.D(~lac_clk90_2), .C(~fpga_clk2x_out), .Q(lac_clk90_3));   FD LAC7 (.D(~lac_clk90_3), .C(~fpga_clk2x_out), .Q(lac_clk90_4));   FD LAC8 (.D(~lac_clk90_4), .C(~fpga_clk2x_out), .Q(fpga_lac_clk90_out));     endmodule // clk_dllsmodule controller (/*AUTOARG*/   // Outputs   ddr_read_en,    ddr_write_en,    u_data_valid_en,    ddr_dqs_t,    ddr_rasb,    ddr_casb,    ddr_web,    ld_burst,    ld_rcd,    ld_cas_lat,    u_ref_ack,    mrs_addr,    row_addr,    // Inputs   u_cmd,    cntlr_reset1,    cntlr_reset2,    cntlr_reset3,    clk,    clk2x, //  clk90,   lac_clk_in,    burst_end,    cas_lat_end,    rcd_end,    burst_8,    burst_2   );         output [3:0] ddr_read_en;      output [7:0] ddr_write_en;   output 	u_data_valid_en;   output 	ddr_dqs_t;   output 	ddr_rasb, ddr_casb, ddr_web;   output 	ld_burst, ld_rcd, ld_cas_lat;   output 	u_ref_ack;   output 	mrs_addr;   output 	row_addr;      input [7:1] 	u_cmd;   input 	cntlr_reset1, cntlr_reset2, cntlr_reset3;    input 	clk, clk2x, lac_clk_in, burst_end, cas_lat_end, rcd_end;   input 	burst_8, burst_2;      reg [2:0] 	ddr_cmd, next_ddr_cmd;   reg [12:1] 	state, next_state;   reg row_addr, ld_cas_lat, ld_burst;   reg ld_rcd;   reg [7:0] ddr_write_en;   reg ddr_dqs_t_wire;   reg u_ref_ack;   reg mrs_addr;   reg ddr_rasb_o, ddr_casb_o, ddr_web_o;   wire data_read = state[`CTLR_READ_DATA];   wire data_write = state[`CTLR_WRITE_DATA];   wire data_read_write = data_read || data_write;   reg read_cmd;   reg read_cmd_reg;   //need to register u_cmd[`SYS_READ] because it's needed to generate burst_end after the user has released the READ command      /*****************/   /* state machine */   /*****************/   always @ (read_cmd_reg or burst_8 or burst_2 or u_cmd or state or burst_end or cas_lat_end or rcd_end)   begin      //has default values for outputs so synthesis tool don't infer latches      next_state = 12'b0000_0000_0000;      read_cmd = 0;      casex (1'b1) 	state[`CTLR_IDLE]   : begin	   casex (1'b1)  	     u_cmd[`SYS_REFRESH]:	next_state[`CTLR_REFRESH] = 1;	     u_cmd[`SYS_PRECHARGE]: 	next_state[`CTLR_PRECHARGE] = 1;	     u_cmd[`SYS_LOAD_MR]:       next_state[`CTLR_LOAD_MR] = 1;	     u_cmd[`SYS_WRITE]:         next_state[`CTLR_ACT] = 1;	     u_cmd[`SYS_READ]: begin			next_state[`CTLR_ACT] = 1;		read_cmd = 1;	     end				     default:   	    	next_state[`CTLR_IDLE] = 1;	   endcase		end // case: state[`CTLR_IDLE]	state[`CTLR_ACT]    : //issue ACTIVE command	   if (rcd_end) begin	      if (read_cmd_reg)	begin			 next_state[`CTLR_READ] = 1;			 read_cmd = 1;	      end	      else begin		 	next_state[`CTLR_WRITE] =1;	      end	   end	   else begin 	      next_state[`CTLR_ACT_WAIT] = 1;	      if (read_cmd_reg)	read_cmd = 1;	   end 	   	state[`CTLR_ACT_WAIT]    :  //issue NOP command, wait for rcd_end	   if (rcd_end) begin	      if (read_cmd_reg)	next_state[`CTLR_READ] = 1;	      else next_state[`CTLR_WRITE] =1;	   end	   else begin	      next_state[`CTLR_ACT_WAIT] = 1;	      if (read_cmd_reg)	read_cmd = 1;	   end	state[`CTLR_READ]  : 	  if (~cas_lat_end)	           next_state[`CTLR_READ_WAIT] = 1;	  else	         	           next_state[`CTLR_READ_DATA] = 1;		state[`CTLR_READ_WAIT]  : 	  if (~cas_lat_end)	           next_state[`CTLR_READ_WAIT] = 1;	  else if (burst_2)                next_state[`CTLR_IDLE] = 1;	  else	                           next_state[`CTLR_READ_DATA] = 1;		state[`CTLR_WRITE]  :	begin	   if (burst_2)                     next_state[`CTLR_IDLE] = 1;	   else                             next_state[`CTLR_WRITE_DATA] = 1;	end		state[`CTLR_READ_DATA]  : 	   if (burst_8 && ~burst_end)      next_state[`CTLR_READ_DATA] = 1;	   else                            next_state[`CTLR_IDLE] = 1;		state[`CTLR_WRITE_DATA]  : begin	   if (burst_8 && ~burst_end)      next_state[`CTLR_WRITE_DATA] = 1;	   else  begin	      next_state[`CTLR_IDLE] = 1;	   end	end	default :               	   next_state[`CTLR_IDLE] = 1;      endcase    end     /*********************************************/   /* combinatorial next state and output logic */   /*********************************************/     wire next_mrs_addr =  u_cmd[`SYS_LOAD_MR];   wire next_row_addr =  ~(next_state[`CTLR_PRECHARGE]|| next_state[`CTLR_READ]|| next_state[`CTLR_WRITE]);     wire next_ld_cas_lat = ~(state[`CTLR_READ] || state[`CTLR_READ_WAIT]);      wire next_ld_burst   = ~(state[`CTLR_READ] || state[`CTLR_WRITE] || data_read_write);      wire next_ld_rcd     = ~(state[`CTLR_ACT] || state[`CTLR_ACT_WAIT]);      wire next_u_ref_ack      =  next_state[`CTLR_REFRESH];      wire next_ddr_rasb_o = ~(state[`CTLR_REFRESH] || state[`CTLR_PRECHARGE] ||        			    state[`CTLR_LOAD_MR] || state[`CTLR_ACT]);   wire next_ddr_casb_o = ~(state[`CTLR_REFRESH] || state[`CTLR_LOAD_MR] ||       			    state[`CTLR_READ] || state[`CTLR_WRITE]);   wire next_ddr_web_o  = ~(state[`CTLR_PRECHARGE] || state[`CTLR_LOAD_MR] || 	                    state[`CTLR_WRITE]);   wire next_ddr_write_en = (state[`CTLR_WRITE] || state[`CTLR_WRITE_DATA]);      wire next_ddr_read_en = state[`CTLR_READ_WAIT] || state[`CTLR_READ_DATA];   reg 	next_ddr_read_en_P1, u_data_valid_en;      always @(posedge clk)  next_ddr_read_en_P1 <= next_ddr_read_en;   wire next_u_data_valid_en = burst_8 ? next_state[`CTLR_READ_WAIT] || next_state[`CTLR_READ_DATA]: (next_state[`CTLR_READ_WAIT] || next_ddr_read_en);//for burst of 4 or 2, need to delay u_data_valid_en      /******************************/   /* output and state registers */   /******************************/   reg [3:0] ddr_read_en;   reg 	     ddr_rasb_o_P1, ddr_casb_o_P1, ddr_web_o_P1;   //ddr control signals are generated on negative edge clock to guarantee DDR hold time   always @ (negedge clk or posedge cntlr_reset1) begin      if (cntlr_reset1) begin		 ddr_rasb_o <= 1;		 ddr_casb_o <= 1;		 ddr_web_o <=1;	       end      else begin		 ddr_rasb_o <= ddr_rasb_o_P1;		 ddr_casb_o <= ddr_casb_o_P1;		 ddr_web_o <= ddr_web_o_P1;      end   end // always @ (posedge clk or posedge cntlr_reset1)      always @ (posedge clk) begin      ddr_rasb_o_P1 <=  next_ddr_rasb_o;      ddr_casb_o_P1 <=  next_ddr_casb_o;      ddr_web_o_P1  <=  next_ddr_web_o;   end   always @ (posedge clk or posedge cntlr_reset2) begin      if (cntlr_reset2) begin		 state[`CTLR_IDLE] <= 1;		 state[`CTLR_REFRESH] <= 0;		 state[`CTLR_PRECHARGE] <= 0;		 state[`CTLR_LOAD_MR] <= 0;		 state[`CTLR_ACT] <= 0;		 state[`CTLR_ACT_WAIT] <= 0;		 state[`CTLR_READ] <= 0;		 state[`CTLR_WRITE] <= 0;		 state[`CTLR_READ_WAIT] <= 0;		 state[`CTLR_READ_DATA] <= 0;		 state[`CTLR_WRITE_DATA] <= 0;		 read_cmd_reg <= 0;      end      else begin		 read_cmd_reg <= read_cmd;		 ddr_read_en <= {4{next_ddr_read_en_P1}};		 mrs_addr <= next_mrs_addr;		 row_addr <= next_row_addr;		 ld_cas_lat <= next_ld_cas_lat;		 ld_burst <= next_ld_burst;		 ld_rcd <= next_ld_rcd;		 u_ref_ack <= next_u_ref_ack;		 state <= next_state;		 u_data_valid_en <= next_u_data_valid_en;      end   end // always @ (posedge clk)   //ddr_write_en is used to enable ddr_dq signals   reg next_ddr_write_en_P1;   always @(posedge clk)      next_ddr_write_en_P1 <= next_ddr_write_en;      always @(posedge clk2x)      ddr_write_en <= {8{next_ddr_write_en_P1}};          //ddr_dqs_t is used to generate ddr_dqs signals   reg ddr_dqs_t_tmp1, ddr_dqs_t_tmp2;   always @(posedge clk) begin      ddr_dqs_t_tmp1 <= next_ddr_write_en;      ddr_dqs_t_tmp2 <= ddr_dqs_t_tmp1;   end      //create local lac_clk and also generate lac_clk_out   FD LAC1 (.D(~lac_clk_in), .C(~clk2x), .Q(lac_clk_out));   FD LAC2 (.D(~lac_clk_in), .C(~clk2x), .Q(lac_clk_wire));   wire #15 lac_clk = lac_clk_wire;   reg 	    ddr_dqs_t;      always @ (negedge clk2x or posedge cntlr_reset3)      if (cntlr_reset3)	ddr_dqs_t <= 1;      else if (lac_clk) ddr_dqs_t <= ~(ddr_dqs_t_tmp1 || next_ddr_write_en);  /*  always @ (negedge clk90 or posedge cntlr_reset3)      if (cntlr_reset3)	ddr_dqs_t <= 1;      else if (lac_clk) ddr_dqs_t <= ~(ddr_dqs_t_tmp1 || next_ddr_write_en);  */   /********************************************/   /* IO buffers for DDR SDRAM control signals */   /********************************************/   OBUF  O_ddr_ras (.O(ddr_rasb), .I(ddr_rasb_o));   OBUF  O_ddr_cas (.O(ddr_casb), .I(ddr_casb_o));   OBUF  O_ddr_we  (.O(ddr_web), .I(ddr_web_o));endmodule // controllermodule cslt_cntr (   cslt_end,    cslt_max, clk,    clk2x,    ld_cslt,    cas_lat_half   );      input [1:0] cslt_max;   input clk, clk2x, ld_cslt, cas_lat_half;   output cslt_end;   reg [1:0]count;   reg 	cslt_end1_5;  //for CAS lat of 1.5 and 2.5, need to delay cslt_end by 1/2 a clk cycle      wire cslt_end1 = ~(|count); //cslt_end goes high when count=0   reg 	cslt_end;      always @ (posedge clk)     cslt_end <= cas_lat_half ? cslt_end1 : cslt_end1_5;      always @ (posedge clk or posedge ld_cslt)     if (ld_cslt)       count <= (cslt_max);     else		count <= count - 1;   always @ (posedge clk2x)     cslt_end1_5 <= cslt_end1;    endmodulemodule data_path (/*AUTOARG*/ 		  // Outputs		  u_data_o, 		  ddr_dqs, 		  u_data_valid, 		  // Inouts		  ddr_dq, 		  // Inputs		  u_data_i, 		  ddr_write_en, 		  ddr_dqs_t, 		  ddr_read_en, 		  u_data_valid_en, 		  clk2x, 		  clk, 		  lac_clk_in, 		  cas_lat_half, 		  burst_8, 		  clk270		  );      input [`U_DATA_MSB:0] u_data_i;

⌨️ 快捷键说明

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