FPGA 控制SDRAM 256M 仿真方法sdram_model_plus

感谢邓堪文大佬 

sdram_model_plus 模块在https://download.csdn.net/download/qq_27841635/11131098

平台:

采用黑金spartan6板子,notepad编辑器,modelsim仿真工具

sdram_model_plus文件太大放在资源里去了,自行下载,敲完代码,伐木累。

给点支持吧

初始化sdram_init模块

module sdram_init(
		//system singles
		input				sclk			,
		input				reset			,
		//others	
		output	reg	[3:0]	cmd_reg			,//输出
		output	wire[12:0]	sdram_addr		,
		output	wire 		flag_init_end	

);
//===============================================================
//*************Define parameter and Internal Singles*************
//===============================================================

localparam		DELAY_200US		=	  10000	;
//SDRAM Command
localparam		NOP				=	 4'b0111;
localparam		PRE				=	 4'b0010;
localparam		AREF			=	 4'b0001;
localparam		MSET			=	 4'b0000;
				reg	[13:0]	cnt_200us			;
				wire		flag_200us			;
				reg	[3:0]	cnt_cmd				;
//===============================================================
//****************    Main Code    ***********
//===============================================================				
//cnt_200us
always@(posedge sclk or negedge reset)begin
		if(!reset)
			cnt_200us	<=	'd0;
		else if(flag_200us == 1'b0)
			cnt_200us	<=	cnt_200us +	1'b1;
end
//cnt_cmd
always@(posedge sclk or negedge reset)begin
		if(!reset)
			cnt_cmd	<=	1'd0;
		else if(flag_200us == 1'b1 && flag_init_end == 1'b0)
			cnt_cmd	<=	cnt_cmd +	1'b1;
end
//cmd_reg
always@(posedge sclk or negedge reset)begin
		if(!reset)
			cmd_reg	<=	NOP;		
		else if(flag_200us == 1'b1)
			case(cnt_cmd)
				0:		cmd_reg	<=	PRE;
				1:		cmd_reg	<=	AREF;
				5:		cmd_reg	<=	AREF;
				9:		cmd_reg	<=	MSET;	
				default:cmd_reg	<=	NOP;
			endcase			
end
//sdram_addr

assign  flag_init_end	=	(cnt_cmd > 10)? 1'b1 : 1'b0;
assign	sdram_addr		=	(cmd_reg == MSET)?	13'b0_0000_00011_0010 : 13'b0_0100_0000_0000;//代表4突发 3潜伏。。。	
assign	flag_200us		=	(cnt_200us >= DELAY_200US)?	 1'b1 :	1'b0;


endmodule

sdram_aref

module sdram_aref(
        //system signals
        input                    sclk            ,
        input                    reset           ,
        //comunicat with ARBIT
        input                    ref_en          ,
        output    reg            ref_req         ,
        output    wire           flag_ref_end    ,
        //others
        output    reg     [3:0]    aref_cmd      ,
        output    wire    [12:0]    sdram_addr   ,
        input                    flag_init_end    
);

//==============================================================================\
//*********************Define Parameter and Internal Signal ********************
//==============================================================================/
localparam        DELAY_78us        =        390        ;//理论上7.5us即可为了刷新完全,多花点时间
localparam        CMD_AREF        	=        4'b0001    ;
localparam        CMD_NOP           =        4'b0111    ;
localparam        CMD_PRE           =        4'b0010    ;
reg        [3:0]            cmd_cnt                    ;
reg        [8:0]            ref_cnt                    ;
reg                        flag_ref               		;//表示在刷新由top产生的使能信号激活,直到刷新结束才为0

//=============================================================================\
//********************** Main Code    ***************************************
//=============================================================================/
always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                ref_cnt <= 9'd0;
        else if(ref_cnt >= DELAY_78us)
                ref_cnt <= 9'd0;
        else if(flag_init_end == 1'b1)
                ref_cnt <= ref_cnt +1'b1;
end

always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                flag_ref <= 1'b0;
        else if(flag_ref_end == 1'b1)
                flag_ref <=    1'b0;
        else if(ref_en == 1'b1)
                flag_ref <= 1'b1;
end

always @(posedge sclk or negedge reset ) begin
        if(reset == 1'b0)
                cmd_cnt    <= 4'd0;
        else if(flag_ref == 1'b1)
                cmd_cnt <= cmd_cnt + 1'b1;
        else
                cmd_cnt <= 4'd0;
end 


always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                aref_cmd <= CMD_NOP;
        else if(cmd_cnt == 2)
               aref_cmd <= CMD_AREF; //预充电 改为刷新时不需要预充电电
        else
			aref_cmd <= CMD_NOP;
end
//ref_req
always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                ref_req <= 0;
		else if(ref_en == 1)		
				ref_req <= 0;
        else if(ref_cnt >= DELAY_78us)
				 ref_req <= 1;
end

assign  flag_ref_end = (cmd_cnt >= 4'd3) ? 1'b1 : 1'b0;
assign    sdram_addr    =    13'd0_0100_0000_0000;




endmodule

 

sdram_write

module sdram_write(
		//system single
		input				sclk,	
		input				reset,
		//commucation with top
		input				wr_en,//现有请求在使能
		output	wire		wr_req,		
		output	reg			flag_wr_end,	
		//others
		input				ref_req,//刷新请求信号
		input				wr_trig,//写触发
		//write interface
		output	reg[3:0]	wr_cmd,
		output	reg[12:0]	wr_addr,
		output	wire[1:0]	bank_addr,
		output	reg[15:0]	wr_data
		
);
/
//
/
//状态
localparam		S_IDLE			=		5'b0_0001;	
localparam		S_REQ			=		5'b0_0010;	
localparam		S_ACT			=		5'b0_0100;//行激活	
localparam		S_WR			=		5'b0_1000;	
localparam		S_PRE			=		5'b1_0000;	
//SDRAM Comand
localparam		CMD_NOP			=		4'b0111;	
localparam		CMD_PRE			=		4'b0010;	
localparam		CMD_AREF		=		4'b0001;	
localparam		CMD_ACT			=		4'b0011;	
localparam		CMD_WR			=		4'b0100;	

reg			flag_wr;//写进行中
reg[4:0]	state;	//5个状态
//*********************************************
reg			flag_act_end;	//4个数据一个act
reg			flag_pre_end;	//写完就激活下一行pre
reg			sd_row_end;		//写一行结束
reg[1:0]	burst_cnt;		//0 1 2 3 
reg[1:0]	burst_cnt_t;	//延迟一拍
reg			wr_data_end;	//两行写完强制结束
//********************************************
reg[3:0]	act_cnt;		//
reg[3:0]	break_cnt;
reg[7:0]	col_cnt;		//列地址计数
//********************************************
reg[12:0]	row_addr;
wire[8:0]	col_addr;
//flag_wr
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_wr	<=	1'b0;
	else if(wr_trig == 1'b1 && flag_wr == 0)
		flag_wr	<=	1'b1;
	else if(wr_data_end == 1'b1)
		flag_wr <= 1'b0;
end
//burst_cnt  突发4计数
always@(posedge sclk or negedge reset)begin
	if(!reset)
		burst_cnt	<=	0;
	else if(state == S_WR)
		burst_cnt	<=	burst_cnt + 1;
	else
		burst_cnt 	<=  0;
end
//burst_cnt_t
always@(posedge sclk or negedge reset)begin
		burst_cnt_t	<= burst_cnt;

end
//--------------------STATE-----------------------
always@(posedge sclk or negedge reset)begin
	if(!reset)
		state	<=	S_IDLE;
	else  case(state)
		S_IDLE:
			if(wr_trig == 1)
				state	<=	S_REQ;
			else	
				state	<=	S_IDLE;
		S_REQ:
			if(wr_en == 1)
				state	<=	S_ACT;
			else	
				state	<=	S_REQ;
		S_ACT:
			if(flag_act_end == 1)//一次突发写完为1
				state	<=  S_WR;
			else
				state	<=	S_ACT;
		S_WR://些状态跳到充电
			if(wr_data_end == 1)
				state	<= S_PRE; //写完两行
			else if(ref_req == 1 && burst_cnt_t == 'd2 && flag_wr == 1)
				state	<=	S_PRE;//刷新到这里 准备 跳出,下几个时钟周期又回来
			else if(sd_row_end == 1 && flag_wr == 1)//写完一行
				state	<=	S_PRE;
		S_PRE:
			if(ref_req == 1 && flag_wr == 1)
				state	<=	S_REQ;
			else if(flag_pre_end == 1 && flag_wr == 1)
				state	<=	S_ACT;
			else if(wr_data_end == 1)
				state	<=	S_IDLE;
		default:
				state	<=	S_IDLE;
	endcase
end
//wr_cmd
always@(posedge sclk or negedge reset)begin
	if(!reset)
		wr_cmd	<=	CMD_NOP;
	else case(state)
		S_ACT:
			if(act_cnt == 0)
				wr_cmd	<=	CMD_ACT;
			else
				wr_cmd	<=	CMD_NOP;
		S_WR:
			if(burst_cnt == 0)
				wr_cmd	<=	CMD_WR;
			else	
				wr_cmd	<=	CMD_NOP;
		S_PRE:
			if(break_cnt == 0)
				wr_cmd	<=	CMD_PRE;
			else	
				wr_cmd	<=	CMD_NOP;
		default:	
				wr_cmd	<=	CMD_NOP;
		endcase	
end


//wr_addr
always@(*)begin//组合逻辑不会延一拍
	 case(state)
		S_ACT:
			if(act_cnt == 0)
				wr_addr	<=	row_addr;
		S_WR:
			wr_addr	<=	{4'b0000,col_addr};		//A10为1,,好像是0
		S_PRE:
			if(break_cnt == 0)
				wr_addr	<=	{13'b0_0100_0000_0000};
	endcase
			
end
	
//---------------------------------------------------
//flag_act_end
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_act_end	<=	0;
	else if(act_cnt == 'd3)
		flag_act_end	<=	1;//相当于第4个别的模块调用已经是第五个了
	else	
		flag_act_end	<=	0;
end
//act_cnt
always@(posedge sclk or negedge reset)begin
	if(!reset)
		act_cnt	<=	0;
	else if(state == S_ACT)//激活需要4个周期包括 命令行地址 延迟3 列地址 
		act_cnt	<=	act_cnt + 1;
	else	
		act_cnt	<=	0;
end

//flag_pre_end //突发为4 结束
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_pre_end	<=	0;
	else if(break_cnt == 'd3)//预充电也需要时间
		flag_pre_end	<=  1;
	else	
		flag_pre_end	<=	0;
end
//
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_wr_end	<=	0;
	else if((state == S_PRE && ref_req == 1) 
			|| (state == S_PRE && wr_data_end == 1))//刷新计数
		flag_wr_end	<=  1;
	else	
		flag_wr_end	<=	0;
end

//break_cnt  //预充电时间
always@(posedge sclk or negedge reset)begin
	if(!reset)
		break_cnt	<=	0;
	else if(state == S_PRE)						
		break_cnt	<=	break_cnt + 1;
	else	
		break_cnt	<=	0;
end
//wr_data_end
always@(posedge sclk or negedge reset)begin
	if(!reset)	
		wr_data_end	<=	0;
	else if(row_addr == 2 && col_addr == 'd511)//自动累加9位 两行写结束//改为3行
		wr_data_end	<=	1;//	
	else
		wr_data_end	<=	0;
end
//col_cnt
always@(posedge sclk or negedge reset)begin
	if(!reset)	
		col_cnt	<=	0;
	else if(col_addr == 511)
		col_cnt	<=	0;
	else if(burst_cnt_t == 3)
		col_cnt	<=	col_cnt + 1;
end
//row_addr
always@(posedge sclk or negedge reset)begin
	if(!reset)	
		row_addr	<=	0;
	else if(sd_row_end == 1)
		row_addr	<=	row_addr + 1;

end
//sd_row_end

always@(posedge sclk or negedge reset)begin
	if(!reset)	
		sd_row_end	<=	0;
	else if(col_addr == 509)
		sd_row_end	<=	1;
	else
		sd_row_end	<=	0;

end


//
always@(*)begin
	case(burst_cnt_t)
		0:wr_data	<=	1;
		1:wr_data	<=	2;
		2:wr_data	<=	3;
		3:wr_data	<=	4;
	default: wr_data	<=	0;
	endcase
end


assign	col_addr	=	{col_cnt,burst_cnt_t};
assign  bank_addr	=	2'b00;//写操作代码 
assign	wr_req		= 	state[1];

endmodule

sdram_read

module sdram_read(
		//system single
		input				sclk,	
		input				reset,
		//commucation with top
		input				rd_en,//现有请求在使能
		output	wire		rd_req,		
		output	reg			flag_rd_end,	
		//others
		input				ref_req,//刷新请求信号
		input				rd_trig,//写触发
		//read interface
		output	reg[3:0]	rd_cmd,
		output	reg[12:0]	rd_addr,
		output	wire[1:0]	bank_addr
		//output	reg[15:0]	rd_data
		
);
/
//
/
//状态
localparam		S_IDLE			=		5'b0_0001;	
localparam		S_REQ			=		5'b0_0010;	
localparam		S_ACT			=		5'b0_0100;//行激活	
localparam		S_RD			=		5'b0_1000;	
localparam		S_PRE			=		5'b1_0000;	
//SDRAM Comand
localparam		CMD_NOP			=		4'b0111;	
localparam		CMD_PRE			=		4'b0010;	
localparam		CMD_AREF		=		4'b0001;	
localparam		CMD_ACT			=		4'b0011;	
localparam		CMD_RD			=		4'b0101;	

reg			flag_rd;//写进行中
reg[4:0]	state;	//5个状态
//*********************************************
reg			flag_act_end;	//4个数据一个act
reg			flag_pre_end;	//写完就激活下一行pre
reg			sd_row_end;		//写一行结束
reg[1:0]	burst_cnt;		//0 1 2 3 
reg[1:0]	burst_cnt_t;	//延迟一拍
reg			rd_data_end;	//两行写完强制结束
//********************************************
reg[3:0]	act_cnt;		//
reg[3:0]	break_cnt;
reg[7:0]	col_cnt;		//列地址计数
//********************************************
reg[12:0]	row_addr;
wire[8:0]	col_addr;
//flag_rd
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_rd	<=	1'b0;
	else if(rd_trig == 1'b1 && flag_rd == 0)
		flag_rd	<=	1'b1;
	else if(rd_data_end == 1'b1)
		flag_rd <= 1'b0;
end
//burst_cnt  突发4计数
always@(posedge sclk or negedge reset)begin
	if(!reset)
		burst_cnt	<=	0;
	else if(state == S_RD)
		burst_cnt	<=	burst_cnt + 1;
	else
		burst_cnt 	<=  0;
end
//burst_cnt_t
always@(posedge sclk or negedge reset)begin
		burst_cnt_t	<= burst_cnt;

end
//--------------------STATE-----------------------
always@(posedge sclk or negedge reset)begin
	if(!reset)
		state	<=	S_IDLE;
	else  case(state)
		S_IDLE:
			if(rd_trig == 1)
				state	<=	S_REQ;
			else	
				state	<=	S_IDLE;
		S_REQ:
			if(rd_en == 1)
				state	<=	S_ACT;
			else	
				state	<=	S_REQ;
		S_ACT:
			if(flag_act_end == 1)//一次突发写完为1
				state	<=  S_RD;
			else
				state	<=	S_ACT;
		S_RD://些状态跳到充电
			if(rd_data_end == 1)
				state	<= S_PRE; //写完两行
			else if(ref_req == 1 && burst_cnt_t == 'd2 && flag_rd == 1)
				state	<=	S_PRE;//刷新到这里 准备 跳出,下几个时钟周期又回来
			else if(sd_row_end == 1 && flag_rd == 1)//写完一行
				state	<=	S_PRE;
		S_PRE:
			if(ref_req == 1 && flag_rd == 1)
				state	<=	S_REQ;
			else if(flag_pre_end == 1 && flag_rd == 1)
				state	<=	S_ACT;
			else if(rd_data_end == 1)
				state	<=	S_IDLE;
		default:
				state	<=	S_IDLE;
	endcase
end
//rd_cmd
always@(posedge sclk or negedge reset)begin
	if(!reset)
		rd_cmd	<=	CMD_NOP;
	else case(state)
		S_ACT:
			if(act_cnt == 0)
				rd_cmd	<=	CMD_ACT;
			else
				rd_cmd	<=	CMD_NOP;
		S_RD:
			if(burst_cnt == 0)
				rd_cmd	<=	CMD_RD;
			else	
				rd_cmd	<=	CMD_NOP;
		S_PRE:
			if(break_cnt == 0)
				rd_cmd	<=	CMD_PRE;
			else	
				rd_cmd	<=	CMD_NOP;
		default:	
				rd_cmd	<=	CMD_NOP;
		endcase	
end


//rd_addr
always@(*)begin//组合逻辑不会延一拍
	 case(state)
		S_ACT:
			if(act_cnt == 0)
				rd_addr	<=	row_addr;
		S_RD:
			rd_addr	<=	{4'b0000,col_addr};		//A10为1,,好像是0
		S_PRE:
			if(break_cnt == 0)
				rd_addr	<=	{13'b0_0100_0000_0000};
	endcase
			
end
	
//---------------------------------------------------
//flag_act_end
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_act_end	<=	0;
	else if(act_cnt == 'd3)
		flag_act_end	<=	1;//相当于第4个别的模块调用已经是第五个了
	else	
		flag_act_end	<=	0;
end
//act_cnt
always@(posedge sclk or negedge reset)begin
	if(!reset)
		act_cnt	<=	0;
	else if(state == S_ACT)//激活需要4个周期包括 命令行地址 延迟3 列地址 
		act_cnt	<=	act_cnt + 1;
	else	
		act_cnt	<=	0;
end

//flag_pre_end //突发为4 结束
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_pre_end	<=	0;
	else if(break_cnt == 'd3)//预充电也需要时间
		flag_pre_end	<=  1;
	else	
		flag_pre_end	<=	0;
end
//
always@(posedge sclk or negedge reset)begin
	if(!reset)
		flag_rd_end	<=	0;
	else if((state == S_PRE && ref_req == 1) 
			|| (state == S_PRE && rd_data_end == 1))//刷新计数
		flag_rd_end	<=  1;
	else	
		flag_rd_end	<=	0;
end

//break_cnt  //预充电时间
always@(posedge sclk or negedge reset)begin
	if(!reset)
		break_cnt	<=	0;
	else if(state == S_PRE)						
		break_cnt	<=	break_cnt + 1;
	else	
		break_cnt	<=	0;
end
//rd_data_end
always@(posedge sclk or negedge reset)begin
	if(!reset)	
		rd_data_end	<=	0;
	else if(row_addr == 2 && col_addr == 'd511)//自动累加9位 两行写结束//改为3行
		rd_data_end	<=	1;//	
	else
		rd_data_end	<=	0;
end
//col_cnt
always@(posedge sclk or negedge reset)begin
	if(!reset)	
		col_cnt	<=	0;
	else if(col_addr == 511)
		col_cnt	<=	0;
	else if(burst_cnt_t == 3)
		col_cnt	<=	col_cnt + 1;
end
//row_addr
always@(posedge sclk or negedge reset)begin
	if(!reset)	
		row_addr	<=	0;
	else if(sd_row_end == 1)
		row_addr	<=	row_addr + 1;

end
//sd_row_end

always@(posedge sclk or negedge reset)begin
	if(!reset)	
		sd_row_end	<=	0;
	else if(col_addr == 509)
		sd_row_end	<=	1;
	else
		sd_row_end	<=	0;

end


//
/*
always@(*)begin
	case(burst_cnt_t)
		0:wr_data	<=	1;
		1:wr_data	<=	2;
		2:wr_data	<=	3;
		3:wr_data	<=	4;
	default: wr_data	<=	0;
	endcase
end
*/

assign	col_addr	=	{col_cnt,burst_cnt_t};
assign  bank_addr	=	2'b00;//写操作代码 
assign	rd_req		= 	state[1];

endmodule

sdram_top

module sdram_top(
		//system singles
		input					sclk			,
		input					reset			,
		//SDRAM Interface
		output	wire			sdram_clk		,
		output	wire			sdram_cke		,
		output	wire			sdram_cs_n		,
		output	wire			sdram_ras_n		,
		output	wire			sdram_cas_n		,
		output	wire			sdram_we_n		,
		output	wire [1:0]		sdram_bank		,
		output	reg  [12:0]		sdram_addr		,
		output	wire [1:0]		sdram_dqm		,
		inout	wire [15:0]		sdram_dq		,
		output	wire	 		flag_init_end	,
		//others
		input					wr_trig			,
		input					rd_trig			
);


//===============================================================
//*************Define parameter and Internal Singles*************
//===============================================================
//仲裁状态机 
localparam        IDLE        =    5'b0_0001        ;
localparam        ARBIT       =    5'b0_0010        ;
localparam        AREF        =    5'b0_0100        ;
localparam		  WRITE		  =	   5'b0_1000		;
localparam		  READ		  =	   5'b1_0000		;

				
				reg[3:0]			sd_cmd			;//各种命令组合起来
//init_main				
				wire [3:0]			init_cmd		;
				wire [12:0]			init_addr		;
//状态机状态
				reg  [4:0]           state          ;
//refresh module
				wire                 ref_req        ;
				wire                 flag_ref_end   ;
				reg                  ref_en         ;//仲裁
				wire [3:0]           ref_cmd        ;
				wire [12:0]          ref_addr       ;
//write module
				reg					 wr_en			;
				wire				 wr_req	        ;
				wire				 flag_wr_end    ;                                
				wire[3:0]			 wr_cmd         ;
				wire[12:0]			 wr_addr        ;
				wire[1:0]			 wr_bank_addr	;	
				wire[15:0]			 wr_data		;
//read module	
				reg					 rd_en			;
				wire				 rd_req			;
				wire				 flag_rd_end	;
//				wire				 ref_req		;	//已经有了刷新命令			
//				wire				 rd_trig		;
				wire[3:0]			 rd_cmd			;
				wire[11:0]			 rd_addr		;
				wire[1:0]			 rd_bank_addr	;

					
always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                state    <=    IDLE;
                
        else case(state)
                IDLE:
                        if(flag_init_end == 1'b1)
                            state <= ARBIT;
                        else
                            state <= IDLE;
                ARBIT://仲裁
                        if(ref_en == 1'b1)
                            state <= AREF;
						else if(wr_en == 1)//写优于读模块
							state <= WRITE;
						else if(rd_en == 1)
							state <= READ;
						else        
                            state <= ARBIT;			
                AREF:
                        if(flag_ref_end == 1'b1)
                            state <= ARBIT;
                        else 
                            state    <=AREF;
				WRITE:
						if(flag_wr_end == 1'b1)
                            state <= ARBIT;
                        else 
                            state    <=WRITE;	
				READ:
						if(flag_rd_end == 1'b1)
                            state <= ARBIT;
                        else 
                            state    <=READ;		
                default: 
                            state <= IDLE;
        endcase
end


//ref_en
always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                ref_en <= 1'b0;
        else if(state == ARBIT && ref_req == 1'b1)
                ref_en <= 1'b1;
        else        
                ref_en <= 1'b0;
end				
//wr_en
always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                wr_en <= 1'b0;
        else if(state == ARBIT && ref_req == 1'b0 && wr_req == 1)
                wr_en <= 1'b1;
        else        
                wr_en <= 1'b0;
end				

//rd_en
always @(posedge sclk or negedge reset) begin
        if(reset == 1'b0)
                rd_en <= 1'b0;
        else if(state == ARBIT && ref_req == 0 && wr_req == 0 && rd_req == 1)
                rd_en <= 1'b1;
        else        
                rd_en <= 1'b0;
end	
					
//===============================================================
//****************    Main Code    ***********
//===============================================================	
//目前只有刷新和写才有的状态
always@(*)begin
		case(state)
				IDLE:begin
					sd_cmd		<=	init_cmd;
					sdram_addr	<=	init_addr;
				end
				AREF:begin
					sd_cmd		<=	ref_cmd;
					sdram_addr	<=	ref_addr;
				end
				WRITE:begin
					sd_cmd		<=	wr_cmd;
					sdram_addr	<=	wr_addr;
				end
				READ:begin
					sd_cmd		<=	rd_cmd;
					sdram_addr	<=	rd_addr;
				end
				default:begin
					sd_cmd		<=	4'b0111;//nop
					sdram_addr	<=	0;
				end
		endcase
end


assign	sdram_cke	=	1'b1;
//assign  sdram_addr  =    (state == IDLE)    ?    init_addr    :    ref_addr;
//assign	{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n}	=	(state == IDLE)    ?    init_cmd    :    ref_cmd;
assign	{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n}	=	sd_cmd;
assign	sdram_dqm	=	2'b00;
assign  sdram_clk	=    ~sclk;//方便sdram采样
assign	sdram_dq	=	(state == WRITE)? wr_data : {16{1'bz}};
assign	sdram_bank  =	(state == WRITE)? wr_bank_addr : rd_bank_addr;

sdram_init sdram_init_inst(
		//system singles
		.sclk					(sclk			),
		.reset					(reset			),
		//others
		.cmd_reg				(init_cmd		),
		.sdram_addr				(init_addr		),
		.flag_init_end			(flag_init_end	)

);

sdram_aref       sdram_aref_inst(
        //system signals
        .sclk                   (sclk           ),
        .reset            	    (reset          ),
        //comunicat with ARBIT
        .ref_en                 (ref_en         ),
        .ref_req                (ref_req        ),
        .flag_ref_end           (flag_ref_end   ),
        //others        
        .aref_cmd               (ref_cmd        ),
        .sdram_addr             (ref_addr       ),
        .flag_init_end          (flag_init_end  )
);
 
sdram_write sdram_write_inst(
		//system single
		.sclk					(sclk			),	
		.reset					(reset			),
		.wr_en					(wr_en			),//现有请求在使能
		.wr_req					(wr_req			),		
		.flag_wr_end			(flag_wr_end	),	
		.ref_req				(ref_req		),//刷新请求信号
		.wr_trig				(wr_trig		),//写触发
		.wr_cmd					(wr_cmd			),
		.wr_addr				(wr_addr		),
		.bank_addr				(wr_bank_addr	),
		.wr_data				(wr_data		)
		
);
sdram_read sdram_read_inst(
		//system single
		.sclk					(sclk			),	
		.reset					(reset			),
		.rd_en					(rd_en			),//现有请求在使能
		.rd_req					(rd_req			),		
		.flag_rd_end			(flag_rd_end	),	
		.ref_req				(ref_req		),//刷新请求信号
		.rd_trig				(rd_trig		),//写触发
		.rd_cmd					(rd_cmd			),
		.rd_addr				(rd_addr		),
		.bank_addr				(rd_bank_addr	)
);




endmodule

tb_sdram_top

`timescale		1ns/1ns

module tb_sdram_top;

reg				sclk;
reg				reset;
//--------------------------
wire			sdram_clk		;
wire			sdram_cke		;
wire			sdram_cs_n		;
wire			sdram_ras_n		;
wire			sdram_cas_n		;
wire			sdram_we_n		;
wire [1:0]		sdram_bank		;
wire [12:0]		sdram_addr		;
wire [1:0]		sdram_dqm		;
wire [15:0]		sdram_dq	    ;
wire			flag_init_end	;

reg				wr_trig			;
reg				rd_trig			;

initial	begin
	wr_trig	<= 0;
	rd_trig	<= 0;
	#205000		//初始化之后才能触发
	wr_trig	<= 1;
	#20			//产生触发脉冲
	wr_trig	<= 0;
	#126500 
	rd_trig	<= 1;
	#20
	rd_trig	<= 0;
end


initial	begin
	sclk	<=	1'b1;
	reset 	<=  1'b0;
	#100
	reset 	<=  1'b1;
end

always	#10		sclk	=	~sclk;
//从定义
defparam		sdram_model_plus_inst.addr_bits		=	13;	//行地址
defparam		sdram_model_plus_inst.data_bits		=	16;	
defparam		sdram_model_plus_inst.col_bits		=	9;	//列地址
defparam		sdram_model_plus_inst.mem_sizes		=	4*1024*1024;//4M





sdram_top sdram_top_inst(
		//system singles
		.sclk					(sclk			),
		.reset					(reset			),
		//SDRAM Interface   
		.sdram_clk				(sdram_clk		),
		.sdram_cke				(sdram_cke		),
		.sdram_cs_n				(sdram_cs_n		),
		.sdram_cas_n			(sdram_cas_n	),
		.sdram_ras_n			(sdram_ras_n	),
		.sdram_we_n				(sdram_we_n		),
		.sdram_bank				(sdram_bank		),
		.sdram_addr				(sdram_addr		),
		.sdram_dqm				(sdram_dqm		),
		.sdram_dq		        (sdram_dq		),
		.flag_init_end			(flag_init_end	),
		.wr_trig				(wr_trig		),
		.rd_trig				(rd_trig		)
);                          

sdram_model_plus sdram_model_plus_inst(
		.Dq						(sdram_dq		), 
		.Addr					(sdram_addr		), 
		.Ba						(sdram_bank		), 
		.Clk					(sdram_clk		), 
		.Cke					(sdram_cke		), 
		.Cs_n					(sdram_cs_n		), 
		.Ras_n					(sdram_ras_n	), 
		.Cas_n					(sdram_cas_n	), 
		.We_n					(sdram_we_n		), 
		.Dqm					(sdram_dqm		),
		.Debug                  (1'b1 			)
);

endmodule

你可能感兴趣的:(FPGA)