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

📄 newsd.v

📁 基于Verilog的完整SDRAM控制器时序代码
💻 V
字号:
`define init_delay 14'd15000`define init_refresh_time 2'd7`define tMRD_delay 1'd1`define refresh_cnt_time 11'd1500		//64ms刷新4096次   定时器实现										//参考sdram的datasheet (64ms/系统时钟)/4096										`define burst_cnt_time_write 4'd7   //突发次数 (1——2——4——8)可用3位`define burst_cnt_time_read 4'd9    //读突发次数 (1——2——4——8)可用3位  FPGA读SDRAM的数,现没有用//根据DATASHEET的控制延时`define tDAL_delay 3'd4					//  5 个周期   读写完成到下一次激活命令的周期数`define tRCD_delay 2'd0					//  1 个周期	激活命令到读写命令的延迟周期数`define tRP_delay 2'd2					//  3个周期		  `define tCAS_delay 2'd2  				//  3个周期		读命令到总线出现数据的延迟周期数`define tRFC_delay 4'd6					//  7个周期  仅初始化时两次自刷新操作的最小间隔周期数module sd_ctrl(clk,rst_n,sd_cke,sd_cs_n,sd_ras_n,sd_cas_n,sd_we_n,sd_dqm,addr,ba,data,irq,state_led,rst_led,hbr_n,hbg_n,rd_en,fifo_rd,fifo_full,rst_v2);input clk,rst_n,hbg_n;output sd_cke,sd_ras_n,sd_cas_n,sd_we_n;output state_led;   			// 总线控制权output rst_led;			// rst							output [1:0] sd_dqm;output [11:0] addr;output [1:0] ba;inout [63:0] data;output [3:0] sd_cs_n;output [3:0] irq;   //irq signal to DSPsoutput hbr_n;output rd_en,rst_v2;input fifo_full;input [63:0] fifo_rd;reg rden,rstv2;assign rd_en=rden;assign rst_v2=rstv2;reg hbr;						//总线仲裁输出  FPGA获reg [11:0] addro;assign hbr_n=hbr;reg [3:0] irq_reg;   //IRQ信号寄存器assign irq=irq_reg;reg [63:0] datatest;		//内部产生的测试数据reg [63:0] datao;			//向SDRAM 输出的数据reg ioro;					//三态控制assign data = ioro?datao:64'hzzzzzzzzzzzzzzzz;reg [12:0] state;				// 状态机 的状态寄存器reg [3:0] add_count;reg [63:0] data_read;		// 从SDRAM 输入reg rst_flag,hbg_flag;     //复位时亮     获得总线控制权时亮assign state_led=hbg_flag;assign rst_led=rst_flag;	always @ (posedge clk)	  if (!rst_n)	  rst_flag<=1'b1;	  else	  rst_flag<=1'b0;	always @ (negedge clk)	  if (hbg_n)	  hbg_flag<=1'b1;	  else	  hbg_flag<=1'b0;	  reg [8:0] wrtime;								//写SDRAM的次数reg [2:0] sd_cmd;	assign {sd_ras_n,sd_cas_n,sd_we_n} = sd_cmd;     //发命令字parameter  cmd_nop 	     	= 3'b111,			//RAS、CAS、WE			  cmd_refresh 	  	= 3'b001,			// fpga刷新   :201的集成SDRAM控制器负责刷															// fpga中仅在初始化时刷新(发此刷新命令两次),															//不再像一般操作中需在数据操作过程中定时刷			  cmd_active   	= 3'b011,			// 激活			  cmd_read_a   	= 3'b101,			// 读命令 (数据流向FPGA)			  cmd_write_a 	  	= 3'b100,			// 写命令			  cmd_precharge 	= 3'b010,			// 预充电			  cmd_mode_set	  	= 3'b000;			// 模式设置 assign sd_cke = 1'b1;					//SDRAM时钟使能   cke上电一直有效assign sd_cs_n = 4'b0000;				//SDRAM片选    cs_n上电一直有效assign sd_dqm = 2'b00;					//高低16位掩码,dqm上reg [11:0] addr;							//12根地址线,行列复用 行4096  列 256reg [1:0] ba;							//块   共4个块 4096 × 列 256)reg [3:0] burst_cnt;						//突发次数reg [2:0] tDAL_cnt;							//tDAL计数reg [1:0] tRCD_cnt,tRP_cnt,tCAS_delay_cnt;	//tRCD,tRP计数,tCAS_delay reg [3:0] tRFC_cnt;							//tRFC计数reg read_write;reg init_delay_cnt_en,init_delay_over;		//reg [13:0] init_delay_cnt;					//初始化计数器 值100~200usreg [1:0] init_refresh_cnt;					//初始化刷新计数器reg refresh_req;							// 定时刷新计数器 的 刷新请求  (现定时刷新计数器没用,由TS201替代)reg refresh_ack;							//定时刷新计数器 的 刷新reg [10:0] refresh_cnt;						//  定 的计数值reg tMRD_cnt;								//MRD 发“reg test_finish;						// 测试完256个数向SDRAM      //主状态机 状态parameter idle         = 13'b0111111111111,		//          power_on     = 13'b1011111111111,		//?????????          auto_refresh = 13'b1101111111111,		//????????          mode_set     = 13'b1110111111111,		//??????          precharge    = 13'b1111011111111,		//?????		    tRFC 	     = 13'b1111101111111,		//RFC????		    tRP          = 13'b1111110111111,		//RP????		    tMRD         = 13'b1111111011111,		//MRD????			 finish       = 13'b1111111101111,          n_idle         = 13'b1000000000000,		//????          n_auto_refresh = 13'b0100000000000,		//?????          n_active       = 13'b0010000000000,		//?????          n_write_a      = 13'b0001000000000,		//????????          n_finish       = 13'b0000100000000,		//????????          n_precharge    = 13'b0000010000000,		//?????		    n_tCAS_delay   = 13'b0000001000000,		//CAS delay??		    n_tRCD         = 13'b0000000100000,		//RCD????		    n_tRP          = 13'b0000000010000,		//RP????		    n_tRFC		    = 13'b0000000001000,		//RFC????		    n_tDAL         = 13'b0000000000100,		//DAL????		    n_read_data    = 13'b0000000000010,		//?????		    n_write_data   = 13'b0000000000001;		//?????always @ (negedge clk or negedge rst_n)	if(!rst_n)                             //复位 操作		begin		state <= power_on;		init_delay_cnt_en <= 1'b0;		init_refresh_cnt <= 2'b00;		tRFC_cnt <= 3'b000;		tRP_cnt<= 1'b0;		tMRD_cnt <= 1'b0;		burst_cnt <= 4'b0000;		tRFC_cnt <= 3'b000;		tDAL_cnt <= 3'b000;		tRP_cnt <= 1'b0;		tRCD_cnt <= 1'b0;		tCAS_delay_cnt <= 1'b0;		read_write <= 1'b0;		test_finish<=1'b0;		ioro<=1'b0;		wrtime<=0;		datao<=0;		irq_reg<=4'b1111;		rstv2<=0;		rden<=0;		end	else		case(state)						//状态转换	////////////////////////////////////////////////					power_on:		begin       					sd_cmd<=cmd_nop;					addr[11:0]<=12'hfff;											init_delay_cnt_en <= 1'b1;						init_refresh_cnt <= 2'b00;		            tRP_cnt<= 1'b0;						tMRD_cnt <= 1'b0;						burst_cnt <= 4'b0000;						tRFC_cnt <= 3'b000;						tDAL_cnt <= 3'b000;						tRP_cnt <= 1'b0;						tRCD_cnt <= 1'b0;						tCAS_delay_cnt <= 1'b0;						read_write <= 1'b0;						test_finish<=1'b0;						hbr<=1'b0;						//总										addro<=12'b010000000000;						add_count<=0;						if(init_delay_over)					//初始化等待 100us						  begin						  init_delay_cnt_en <= 1'b0;						  state <= precharge;						  end							else						  begin						  state <= power_on;						  sd_cmd<=cmd_nop;						  end					  end		////////////////////////////////////////////////				  		idle:			begin						datao<=64'hffffffffffffffff;						state<=n_idle;						addr[11:0]<=12'hfff;						sd_cmd<=cmd_nop;					   end		////////////////////////////////////////////////							auto_refresh:	begin							sd_cmd <= cmd_refresh;							addr[11:0]<=12'hfff;							ba<=2'b00;							if(init_refresh_cnt == `init_refresh_time)		//????????????							  begin 							   state <= tRFC;							  end							else								begin								init_refresh_cnt <= init_refresh_cnt + 2'b01;								state <= tRFC;								end							end		////////////////////////////////////////////////								mode_set:	begin		            if(test_finish)							begin							 init_refresh_cnt <= 2'b00;							 sd_cmd <= cmd_mode_set;							 addr[11:0]<=12'b000000100111;     //CL=2,full-page burst,to match the TS201 SDram controller							 state <= tMRD;							end						else						   begin							 init_refresh_cnt <= 2'b00;							 sd_cmd <= cmd_mode_set;							 addr[11:0]<=12'b000000100011;     //CL=2,8 burst,to match the TS201 SDram controller							 state <= tMRD;							end						end								////////////////////////////////////////////////								precharge:		begin							state <= tRP;							sd_cmd <= cmd_precharge;							addr[10]<=1'b1;						end	   tRP:			begin						sd_cmd <= cmd_nop;						addr[11:0]<=12'hfff;													if(tRP_cnt == `tRP_delay)								begin								tRP_cnt <= 2'b00;								state <= auto_refresh;								end							else								begin								tRP_cnt <= tRP_cnt + 2'b01;								state <= tRP;								end							end		////////////////////////////////////////////////								tRFC:			begin						sd_cmd <= cmd_nop;							if(tRFC_cnt == `tRFC_delay)								begin								tRFC_cnt <= 4'b0000;								if(init_refresh_cnt == 2'b11)									state <= mode_set;								else									begin									init_refresh_cnt <= init_refresh_cnt + 2'b01;									state <= auto_refresh;									end								end						else							begin							tRFC_cnt <= tRFC_cnt + 4'b0001;							state <= tRFC;							end						end	////////////////////////////////////////////////							tMRD:		begin               if(test_finish)				            begin			            sd_cmd <= cmd_nop;							if(tMRD_cnt == `tMRD_delay)								begin								tMRD_cnt <= 1'b0;								state <= n_finish;								addr<=0;								end							else								begin								tMRD_cnt <= 1'b1;								state <= tMRD;								end						end					 else		            begin			            sd_cmd <= cmd_nop;							if(tMRD_cnt == `tMRD_delay)								begin								tMRD_cnt <= 1'b0;								state <= n_idle;								addr<=0;								end							else								begin								tMRD_cnt <= 1'b1;								state <= tMRD;								end						end                end								////////////////////////////////////////////////							 n_idle:		//		 begin//						if(add_count>7)//							begin//							test_finish<=1;//							state<=precharge;//							end//						else																			begin							datao<=64'hffffffffffffffff;							sd_cmd <= cmd_nop;							if (wrtime>=32)							  if(add_count==7)							    begin							    test_finish<=1;							    state<=precharge;							    end							  else								  begin									  add_count<=add_count+1;									  state<=n_active;									  addro<=12'b010000000000;									  wrtime<=0;								  end							else								begin								hbr<=1'b0;								state <= n_active;								end						  end 		////////////////////////////////////////////////	       n_auto_refresh:	begin						      sd_cmd <= cmd_refresh;																refresh_ack <= 1'b0;								state <= n_tRFC;								end		////////////////////////////////////////////////								    n_active:			begin				              datao<=64'hffffffffffffffff;				              addr<=add_count;								  								  ba<=2'b00;	        	              sd_cmd <= cmd_active;								  state <= n_tRCD;								end		////////////////////////////////////////////////									n_write_a:			begin				            sd_cmd <= cmd_write_a;				            								addr<=addro;				            datao<=datatest; 								ioro<=1'b1;				            								state <= n_write_data;																end		////////////////////////////////////////////////									n_finish:			begin				            sd_cmd <= cmd_active;   //use "active" to break full-page burst				            addr<=33;								irq_reg<=4'b0000;                        ioro<=1'b0;				            addr<=12'bzzzzzzzzzzzz;								sd_cmd<=3'bzzz;								hbr<=1'b1;								state<=finish;								end		////////////////////////////////////////////////       finish:          begin		                  sd_cmd <= 3'bzzz;				            irq_reg<=4'b1111;                        ioro<=1'b0;				            addr<=12'bzzzzzzzzzzzz;								sd_cmd<=3'bzzz;								state <= finish;								hbr<=1'b1;								end				////////////////////////////////////////////////								    n_precharge:		begin	        	            sd_cmd <= cmd_precharge;								state <= n_tRP;								end		////////////////////////////////////////////////									n_tRP:		begin							sd_cmd <= cmd_nop;				    							if(tRP_cnt == `tRP_delay)								begin								tRP_cnt <= 2'b00;								state <= n_auto_refresh;								end							else								begin								tRP_cnt <= tRP_cnt + 2'b01;								state <= n_tRP;								end					   end		////////////////////////////////////////////////									n_tRFC:			begin							sd_cmd <= cmd_nop;				   								if(tRFC_cnt == `tRFC_delay)									begin									tRFC_cnt <= 4'b0000;									state <= n_idle;									end								else									begin									tRFC_cnt <= tRFC_cnt + 4'b0001;									state <= n_tRFC;									end							end		////////////////////////////////////////////////									n_tRCD:			begin							sd_cmd <= cmd_nop;								if(tRCD_cnt == `tRCD_delay)									begin									tRCD_cnt <= 2'b00;                           state <= n_write_a;									end								else									begin									tRCD_cnt <= tRCD_cnt + 2'b01;									state <= n_tRCD;									end							end	////////////////////////////////////////////////			n_tDAL:	 		begin   //4个周期				            sd_cmd <= cmd_nop;				            				            								if(tDAL_cnt == `tDAL_delay)									begin									tDAL_cnt <= 3'b000;									state <= n_idle;									addro[11:0]<=addro+8;									end								else									begin									tDAL_cnt <= tDAL_cnt + 3'b001;									state <= n_tDAL;									end							end		////////////////////////////////////////////////			n_write_data:		begin				               sd_cmd <= cmd_nop;                           datao<=datatest; 								if(burst_cnt == `burst_cnt_time_write)									begin									burst_cnt <= 4'b0000;									state <= n_tDAL;									wrtime<=wrtime+1;									end								else									begin									burst_cnt <= burst_cnt + 4'b0001;									state <= n_write_data;																				end										end								default:		state <= power_on;	endcase	//////////初始化计数器///////////////////////	always @ (negedge clk or negedge rst_n)						//初始化计数150us  if(!rst_n)    begin    init_delay_over <= 1'b0;    init_delay_cnt <= 14'd0;    end  else    if(init_delay_cnt_en)      if(init_delay_cnt == `init_delay)	//150us约15000个周期        begin        init_delay_over <= 1'b1;        init_delay_cnt <= 14'd0;        end      else        init_delay_cnt <= init_delay_cnt + 14'd1;    else      init_delay_cnt <= 14'd0;//////////生成测试数据///////////////////////	always @ (posedge clk)   if (state==power_on)	  datatest<=64'h8080000010000000;	  else	    begin	    if(state==n_write_data)	     begin	     datatest<=datatest+1;	     end	    else				;              //完整的IF结构  编程风		end/////////////////////////////////		  //always @ (negedge clk or negedge rst_n)//	if (!rst_n)//		begin//		refresh_req <= 1'b0;//		refresh_cnt <= 11'b00000000000;//		end//	else//			begin//		//			if(refresh_cnt == `refresh_cnt_time)		//64ms??8192???1015.625??,1000//				begin//				refresh_cnt <= 11'b00000000000;//				refresh_req <= 1'b1;//				end//			else//				begin//				refresh_cnt <= refresh_cnt + 11'b00000000001;//				end//			if(refresh_ack)//				refresh_req <= 1'b0;//			else//				;//			endendmodule

⌨️ 快捷键说明

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