W5500 FPGA 之一(Ping)

W5500 FPGA 之一(SPI接口)

FPGA似乎成为我的救命稻草。2007年开始接触Xilinx的FPGA,经过五年的学习,竟又放下了七年。近两年又开始做Altera的FPGA。现在用低成本EP4CE10E22比较顺手,可以把FPGA当作CPU来用。

最近要做一个语音采集,并要把语音推送到局域网上,不得已要用到W5500(其实对FPGA而言,应该选用W5300,不过换芯片应该是容易的,就是把SPI接口换成并口)。首先记录一下SPI接口。

一 SPI接口

多年已经习惯直接用SignalTap或者Chipscope,都忘记Modsim怎么用了。太喜欢Quartus,因为Vivado的Chipscope做得太烂,动不动就编译不过。先放源代码

//端口定义
module W5500(
       input            Clk,   
		 output reg       Reset,              //0:Reset  1:Work
       output reg       CH378SPI_DO,        //CH378
		 input            CH378SPI_DI,        //CH378
		 output reg       CH378SPI_Clk,       //CH378
		 output reg       CH378SPI_CS
  );
//硬件复位
reg[15:0] Reset_Counter;
always@(posedge Clk)
begin
     if(Reset_Counter<60000) begin   Reset_Counter<=Reset_Counter+1;  end
	  else                    begin   Reset_Counter<=Reset_Counter;    end
	  
	  if((100<Reset_Counter)&&(Reset_Counter<50000)) Reset<=0;
	  else                                           Reset<=1;
end	

//变量定义
reg       SPI_Send_Start,SPI_Send_Start_1,SPI_Send_Start_2,SPI_Send_Start_3;
reg[7:0]  SPI_Period;
reg[15:0] SPI_Address,SPI_Address_1;
reg[7:0]  SPI_Control,SPI_Control_1;
reg[47:0] SPI_Data;
reg[7:0]  SPI_Data1,SPI_Data2,SPI_Data3,SPI_Data4,SPI_Data5,SPI_Data6;
reg[7:0]  Address_Len,Control_Len,Data_Len,Data_Len_1;
reg       WR;  //1:Write  0:Read
//SPI接口
always@(posedge Clk)
begin
     if(Reset==0)
	  begin
	       CH378SPI_CS<=1;
			 CH378SPI_Clk<=0;
			 CH378SPI_DO<=0;
	  end
     else if((SPI_Send_Start_2==1)&&(SPI_Send_Start_3==0)) //上升沿触发SPI
	  begin
			 CH378SPI_CS<=0;
			 CH378SPI_Clk<=0;
			 
			 SPI_Address<=SPI_Address_1;   //参数装载
			 SPI_Control<=SPI_Control_1;
			 SPI_Data<={SPI_Data1,SPI_Data2,SPI_Data3,SPI_Data4,SPI_Data5,SPI_Data6};
			 
			 Address_Len<=16;             //地址长度是固定的
			 Control_Len<=8;                //控制段长度也是固定的
			 Data_Len<=Data_Len_1;  //数据段是可变的,本段程序最多可收发6个字节
	  end
	  else if(Address_Len>=1)
	  begin
			 if     (SPI_Period==0)   CH378SPI_DO<=SPI_Address[Address_Len-1];
			 else if(SPI_Period==15)  CH378SPI_Clk<=1;
			 else if(SPI_Period==30)  CH378SPI_Clk<=0;
			 else if(SPI_Period==34)  Address_Len<=Address_Len-1;
	  end
	  else if(Control_Len>=1)
	  begin
			 if     (SPI_Period==0)   CH378SPI_DO<=SPI_Control[Control_Len-1];
			 else if(SPI_Period==15)  CH378SPI_Clk<=1;
			 else if(SPI_Period==30)  CH378SPI_Clk<=0;
			 else if(SPI_Period==34)  Control_Len<=Control_Len-1;
	  end
	  else if(Data_Len>=1)
	  begin
			 if     (SPI_Period==0)   CH378SPI_DO<=SPI_Data[Data_Len-1]&WR;
			 else if(SPI_Period==15)  CH378SPI_Clk<=1;
			 else if(SPI_Period==30)  CH378SPI_Clk<=0;
			 else if(SPI_Period==34)  Data_Len<=Data_Len-1;
	  end
	  
	  else if(Data_Len==0)
	  begin
	       CH378SPI_CS<=1;
	  end  
	  
	  if((SPI_Send_Start_2==1)&&(SPI_Send_Start_3==0))  SPI_Period<=0; 
	  else if(SPI_Period<35)                          SPI_Period<=SPI_Period+1;
	  else                                            SPI_Period<=0;
	  
	  SPI_Send_Start_3<=SPI_Send_Start_2;
	  SPI_Send_Start_2<=SPI_Send_Start_1;
	  SPI_Send_Start_1<=SPI_Send_Start;
end

要启动“SPI接口”这段程序,需要有几点前提:1.装置参数 SPI_Address_1; SPI_Control_1;{SPI_Data1,SPI_Data2,SPI_Data3,SPI_Data4,SPI_Data5,SPI_Data6};
2.开启触发信号SPI_Send_Start的上升沿
下面一段程序就是设置各个寄存器

reg[32:0] Cycle_Counter;
always@(posedge Clk)
begin
     if(Cycle_Counter<330000000)    Cycle_Counter<=Cycle_Counter+1;
	  else                             Cycle_Counter<=Cycle_Counter;
	  //定时器支持8秒运行,不循环
	  
	  if(Cycle_Counter==200012000)        //写入 通用MR 软件复位 
	  begin 
	       SPI_Send_Start<=0;  
	  end
	  else if(Cycle_Counter==200012010)          
	  begin 
	       WR<=1;
	       SPI_Control_1<=8'h04;    //Write
			 SPI_Address_1<=MR;
			 SPI_Data6<=8'h80;
			 Data_Len_1<=8;     //32Bit 
			 SPI_Send_Start<=1;  
	  end
	  
	  
	  330000000
	  else if     (Cycle_Counter==300000000)        //写入网关    
	  begin 
	       SPI_Send_Start<=0;  
	  end
	  else if(Cycle_Counter==300000010)          
	  begin 
	       WR<=1;
	       SPI_Control_1<=8'h04;    //Write
			 SPI_Address_1<=GAR;
			 SPI_Data3<=192;
			 SPI_Data4<=168;
			 SPI_Data5<=1;
			 SPI_Data6<=1;
			 Data_Len_1<=32;     //32Bit 
			 SPI_Send_Start<=1;  
	  end
	  
	  else if(Cycle_Counter==300003000)        //写入子网掩码    
	  begin 
	       SPI_Send_Start<=0;  
	  end
	  else if(Cycle_Counter==300003010)          
	  begin 
	       WR<=1;
	       SPI_Control_1<=8'h04;    //Write
			 SPI_Address_1<=SUBR;
			 SPI_Data3<=255;
			 SPI_Data4<=255;
			 SPI_Data5<=255;
			 SPI_Data6<=0;
			 Data_Len_1<=32;     //32Bit 
			 SPI_Send_Start<=1;  
	  end
	  
	  else if(Cycle_Counter==300006000)        //写入物理地址    
	  begin 
	       SPI_Send_Start<=0;  
	  end
	  else if(Cycle_Counter==300006010)          
	  begin 
	       WR<=1;
	       SPI_Control_1<=8'h04;    //Write
			 SPI_Address_1<=SHAR;
			 SPI_Data1<=8'h0C;
			 SPI_Data2<=8'h29;
			 SPI_Data3<=8'hAB;
			 SPI_Data4<=8'h7C;
			 SPI_Data5<=8'h00;
			 SPI_Data6<=8'h01;
			 Data_Len_1<=48;     //32Bit 
			 SPI_Send_Start<=1;  
	  end
	  
	  else if(Cycle_Counter==300009000)        //写入IP    
	  begin 
	       SPI_Send_Start<=0;  
	  end
	  else if(Cycle_Counter==300009010)          
	  begin 
	       WR<=1;
	       SPI_Control_1<=8'h04;    //Write
			 SPI_Address_1<=SIPR;
			 SPI_Data3<=192;
			 SPI_Data4<=168;
			 SPI_Data5<=1;
			 SPI_Data6<=199;
			 Data_Len_1<=32;     //32Bit 
			 SPI_Send_Start<=1;  
	  end
	  
	  else if(Cycle_Counter==300012000)        //写入Mode    
	  begin 
	       SPI_Send_Start<=0;  
	  end
	  else if(Cycle_Counter==300012010)          
	  begin 
	       WR<=1;
	       SPI_Control_1<=8'h04;    //Write
			 SPI_Address_1<=MR;
			 SPI_Data6<=8'h00;
			 Data_Len_1<=8;     //32Bit 
			 SPI_Send_Start<=1;  
	  end

读的指令如下

else if(Cycle_Counter==300024000) 
	  begin 
	       SPI_Send_Start<=0;          
	  end
	  else if(Cycle_Counter==300024010) 
	  begin 
	       WR<=0;
	       SPI_Control_1<=8'h00;    //Read
			 SPI_Address_1<=MR;
			 Data_Len_1<=8;     //8Bit
			 SPI_Send_Start<=1;  
	  end

SPI的波形如下,只显示了一段。DI端有些奇怪,W5500自己会蹦一些波形出来,但不会影响SPI读的操作,到DI回传数据时,DI就恢复正常了。
在这里插入图片描述

这是我第一次写博客,感觉还是有些麻烦。但这个过程可以分享自己的程序,也能给自己一个总结,很好!

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值