quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试

开发板使用的是EP4CE15F23C8,软件使用的是quartus  12.1 ,工程主要是对24c04进行读写

eeprom顶层

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    eeprom_top 
// Function: write and read eeprom using I2C bus
//////////////////////////////////////////////////////////////////////////////////
module eeprom_top
(
    input CLK_50M,
	 input RSTn,
	 output [3:0]LED,
	 
	 output SCL,
	 inout SDA
);
  
  
wire [7:0] RdData;
wire Done_Sig;

reg [3:0] i;
reg [3:0] rLED;

reg [7:0] rAddr;
reg [7:0] rData;
reg [1:0] isStart;

assign LED = rLED;

/***************************/
/*   EEPROM write and read */
/***************************/	  
always @ ( posedge CLK_50M or negedge RSTn )	
	 if( !RSTn ) begin
			i <= 4'd0;
			rAddr <= 8'd0;
			rData <= 8'd0;
			isStart <= 2'b00;
         rLED <= 4'b0000;
	 end
	 else
		case( i )
				
	     0:
		  if( Done_Sig ) begin isStart <= 2'b00; i <= i + 1'b1; end
		  else begin isStart <= 2'b01; rData <= 8'h12; rAddr <= 8'd0; end              //eeprom write 0x12 to EEPROM addr 0
					 
		  1:
		  if( Done_Sig ) begin isStart <= 2'b00; i <= i + 1'b1; end
		  else begin isStart <= 2'b10; rAddr <= 8'd0; end                              //eeprom read data from EEPROM addr 0
					 
		  2:
		  begin rLED <= RdData[3:0]; end		
		
		endcase	
	 
/***************************/
//I2C通信程序//
/***************************/				
iic_control U1
	 (
	     .CLK         ( CLK_50M ),
		  .RSTn        ( RSTn ),
		  .Start_Sig   ( isStart ),
		  .Addr_Sig    ( rAddr ),
		  .WrData      ( rData ),
		  .RdData      ( RdData ),
		  .Done_Sig    ( Done_Sig ),
	     .SCL         ( SCL ),
		  .SDA         ( SDA )
);


endmodule

iic 控制模块

module iic_control
(
    input CLK,
	 input RSTn,
	 
	 input [1:0] Start_Sig,             //read or write command
	 input [7:0] Addr_Sig,              //eeprom words address
	 input [7:0] WrData,                //eeprom write data
	 output [7:0] RdData,               //eeprom read data
	 output Done_Sig,                   //eeprom read/write finish
	 
	 output SCL,
	 inout SDA
	 
);

parameter F100K = 9'd500;              //100Khz的时钟分频系数  
              
	 
reg [4:0]i;
reg [4:0]Go;
reg [9:0]C1;
reg [7:0]rData;
reg rSCL;
reg rSDA;
reg isAck;
reg isDone;
reg isOut;	
 
assign Done_Sig = isDone;
assign RdData = rData;
assign SCL = rSCL;
assign SDA = isOut ? rSDA : 1'bz;       //SDA数据输出选择

//****************************************// 
//*             I2C读写处理程序            *// 
//****************************************// 
always @ ( posedge CLK or negedge RSTn )
	 if( !RSTn )  begin
			i <= 5'd0;
			Go <= 5'd0;
			C1 <= 9'd0;
			rData <= 8'd0;
			rSCL <= 1'b1;
			rSDA <= 1'b1;
			isAck <= 1'b1;
			isDone <= 1'b0;
			isOut <= 1'b1;
	 end
	 else if( Start_Sig[0] )                     //I2C 数据写
	     case( i )
				    
		    0: // iic Start
			 begin
					isOut <= 1;                         //SDA端口输出
					
					if( C1 == 0 ) rSCL <= 1'b1;
					else if( C1 == 400 ) rSCL <= 1'b0;       //SCL由高变低
							  
					if( C1 == 0 ) rSDA <= 1'b1; 
					else if( C1 == 200 ) rSDA <= 1'b0;        //SDA先由高变低 
							  
					if( C1 == F100K -1) begin C1 <= 9'd0; i <= i + 1'b1; end
					else C1 <= C1 + 1'b1;
			 end
					  
			 1: // Write Device Addr
			 begin rData <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end         
				 
			 2: // Wirte Word Addr
			 begin rData <= Addr_Sig; i <= 5'd7; Go <= i + 1'b1; end
					
			 3: // Write Data
			 begin rData <= WrData; i <= 5'd7; Go <= i + 1'b1; end
	 
			 4: //iic Stop
			 begin
			    isOut <= 1'b1;
						  
			    if( C1 == 0 ) rSCL <= 1'b0;
			    else if( C1 == 100 ) rSCL <= 1'b1;     //SCL先由低变高       
		
				 if( C1 == 0 ) rSDA <= 1'b0;
				 else if( C1 == 300 ) rSDA <= 1'b1;     //SDA由低变高  
					 	  
				 if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
				 else C1 <= C1 + 1'b1; 
			 end
					 
			 5:
			 begin isDone <= 1'b1; i <= i + 1'b1; end       //写I2C 结束
					 
			 6: 
			 begin isDone <= 1'b0; i <= 5'd0; end
				 
			 7,8,9,10,11,12,13,14:                         //发送Device Addr/Word Addr/Write Data
			 begin
			     isOut <= 1'b1;
				  rSDA <= rData[14-i];                      //高位先发送
					  
				  if( C1 == 0 ) rSCL <= 1'b0;
			     else if( C1 == 100 ) rSCL <= 1'b1;
				  else if( C1 == 300 ) rSCL <= 1'b0; 
						  
				  if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
				  else C1 <= C1 + 1'b1;
			 end
					 
			 15:                                          // waiting for acknowledge
			 begin
			     isOut <= 1'b0;                            //SDA端口改为输入
			     if( C1 == 100 ) isAck <= SDA;
						  
				  if( C1 == 0 ) rSCL <= 1'b0;
				  else if( C1 == 100 ) rSCL <= 1'b1;
				  else if( C1 == 300 ) rSCL <= 1'b0;
						  
				  if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
				  else C1 <= C1 + 1'b1; 
			 end
					 
			 16:
			 if( isAck != 0 ) i <= 5'd0;
			 else i <= Go; 
					
  		    endcase
	
	  else if( Start_Sig[1] )                     //I2C 数据读
		    case( i )
				
			 0: //iic Start
			 begin
			      isOut <= 1;                      //SDA端口输出
					      
			      if( C1 == 0 ) rSCL <= 1'b1;
			 	   else if( C1 == 400 ) rSCL <= 1'b0;      //SCL由高变低
						  
					if( C1 == 0 ) rSDA <= 1'b1; 
					else if( C1 == 200 ) rSDA <= 1'b0;     //SDA先由高变低 
						  
					if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
					 else C1 <= C1 + 1'b1;
			 end
					  
			 1: // Write Device Addr
			 begin rData <= {4'b1010, 3'b000, 1'b0}; i <= 5'd9; Go <= i + 1'b1; end
					 
			 2: // Wirte Word Addr
			 begin rData <= Addr_Sig; i <= 5'd9; Go <= i + 1'b1; end
					
			 3: //iic Start again
			 begin
			     isOut <= 1'b1;
					      
			     if( C1 == 0 ) rSCL <= 1'b0;
				  else if( C1 == 100 ) rSCL <= 1'b1;
				  else if( C1 == 500 ) rSCL <= 1'b0;                //SCL后变低      
						  
			     if( C1 == 0 ) rSDA <= 1'b0; 
				  else if( C1 == 100 ) rSDA <= 1'b1;
				  else if( C1 == 300 ) rSDA <= 1'b0;                //SDA先变低
						  
				  if( C1 == 600 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
				  else C1 <= C1 + 1'b1;
			 end
					 
			 4: // Write Device Addr ( Read )
			 begin rData <= {4'b1010, 3'b000, 1'b1}; i <= 5'd9; Go <= i + 1'b1; end
					
			 5: // Read Data
			 begin rData <= 8'd0; i <= 5'd19; Go <= i + 1'b1; end
				 
			 6: //iic Stop
			 begin
			     isOut <= 1'b1;
			     if( C1 == 0 ) rSCL <= 1'b0;
				  else if( C1 == 100 ) rSCL <= 1'b1;            //SCL先变高
		
				  if( C1 == 0 ) rSDA <= 1'b0;
				  else if( C1 == 300 ) rSDA <= 1'b1;            //SDA后变高
					 	  
				  if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
				  else C1 <= C1 + 1'b1; 
			 end
					 
			 7:                                                       //写I2C 结束
			 begin isDone <= 1'b1; i <= i + 1'b1; end
					 
			 8: 
			 begin isDone <= 1'b0; i <= 5'd0; end
				 
					
			 9,10,11,12,13,14,15,16:                                  //发送Device Addr(write)/Word Addr/Device Addr(read)
			 begin
			      isOut <= 1'b1;					      
			 	   rSDA <= rData[16-i];
						  
				   if( C1 == 0 ) rSCL <= 1'b0;
					else if( C1 == 100 ) rSCL <= 1'b1;
					else if( C1 == 300 ) rSCL <= 1'b0; 
						  
					if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
					else C1 <= C1 + 1'b1;
			 end
			       
			 17: // waiting for acknowledge
			 begin
			      isOut <= 1'b0;                                       //SDA端口改为输入
					     
			 	   if( C1 == 200 ) isAck <= SDA;
						  
					if( C1 == 0 ) rSCL <= 1'b0;
					else if( C1 == 100 ) rSCL <= 1'b1;
					else if( C1 == 300 ) rSCL <= 1'b0;
						  
					if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
					else C1 <= C1 + 1'b1; 
			 end
					 
			 18:
			      if( isAck != 0 ) i <= 5'd0;
					else i <= Go;
					 
					 
			 19,20,21,22,23,24,25,26: // Read data
			 begin
			     isOut <= 1'b0;
			     if( C1 == 200 ) rData[26-i] <= SDA;
						  
				  if( C1 == 0 ) rSCL <= 1'b0;
				  else if( C1 == 100 ) rSCL <= 1'b1;
				  else if( C1 == 300 ) rSCL <= 1'b0; 
						  
				  if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
				  else C1 <= C1 + 1'b1;
			 end	  
					 
			 27: // no acknowledge
			 begin
			     isOut <= 1'b1;
					  
				  if( C1 == 0 ) rSCL <= 1'b0;
				  else if( C1 == 100 ) rSCL <= 1'b1;
				  else if( C1 == 300 ) rSCL <= 1'b0;
						  
				  if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= Go; end
				  else C1 <= C1 + 1'b1; 
			end
				
			endcase	
	   	
		

	
				
endmodule

使用iic对eeprom进行读写,这个工程主要要注意iic协议的起始信号,停止信号,以及ack,并且要清楚如何使用三态门,将一个

IO口设置为双向口,程序部分要注意状态机里GO这个是如何跳转的

设置管脚

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第1张图片

点击工具栏快捷按钮进行编译

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第2张图片

使用Signaltap 观测端口信号
点击工具栏上的Open按钮,然后选择Signaltap Ⅱ Logic Analyzer File,点击OK

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第3张图片

点击截图中的红色方框添加采样时钟

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第4张图片

这里的CLK_50M来自顶层,点击List将CLK_50M添加进来

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第5张图片

选择CLK_50M,点击 > 将CLK_50M添加进来

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第6张图片

点击OK

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第7张图片

双击空白添加想要观测的信号管脚

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第8张图片

添加管脚SCL,点击List

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第9张图片

这里因顶层例化的模块里有相同的管脚名所以都加进来,但我们只选外接的eeprom模块的这个管脚,点击 >  加入进来

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第10张图片

点击OK

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第11张图片

添加SDA管脚,输入管脚名SDA,点击List,在下面的管脚列表里选择SDA,再点击 > 添加进去 

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第12张图片

添加RdData,输入RdData名称,点击List,选择列表里的RdData,点击 >  添加进来

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第13张图片

点击OK

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第14张图片

SignalTap 就配置完了,按ctrl+s保存 SignalTap 文件为 stp1.stp

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第15张图片

关闭SignalTap 界面在quartus里重新编译工程,双击者个Files里的step1.stp文件打开 SignalTap

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第16张图片

连接USB Blaster 下载器,可以看到我们的开发板型号

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第17张图片

点击 SOF Manager 最右边的按钮,并选择生成的 eeprom_test.sof 文件

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第18张图片

点击Open添加进来

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第19张图片

点击下载按钮下载进去

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第20张图片

下载完成后,如下图所示

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第21张图片

将SDA设置为下降沿触发

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第22张图片

点击 Run Analysis 按钮开始运行一次 SignalTap 的数据采集
quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第23张图片

SignalTap  处于等待状态,按一下开发板的reset按键

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第24张图片

触发IIC总线,采集到的波形如下图所示

quartus Ⅱ 12.1 使用教程(5) eeprom 读写测试_第25张图片

你可能感兴趣的:(quartus,Ⅱ)