基于FPGA的APS6404L-3SQR QSPI PSRAM驱动设计(2)

1.摘要

上一篇文章 基于FPGA的APS6404L-3SQR QSPI PSRAM驱动设计(1)主要记录了数据手册和设计中框架,这里记录一下具体的spi协议相关的设计。

在PSRAM的众多命令中有一些命令用spi协议控制更方便(我感觉)。比如两个复位命令66和99,在没配置QPI命令模式之前只能用SPI协议,所以类似复位命令这些指令如(良品检测、配置QPI和边界选择)都使用SPI来控制即可。

这些协议中除了良品检测命令其他都只是需要简单发送8bit命令,利用spi协议发送简单的一批。对于良品检测命令就需要用到状态机控制了,分别写命令+写地址+读数据了,稍微复杂一点。

2.FPGA设计

2.1、时序图设计

当spi模块的状态机跳转到写命令状态时,即可开始向PSRAM芯片写入命令,具体工作过程如时序图所示:

具体设计思路为:

状态机检测到命令输入立刻从IDLE跳转到SPI_CMD,同时spi工作有效信号r_run拉高。因为是8bit命令,所以计数器r_cnt计数0-7,r_spi_cnt作为计数器标志信号,通过在spi有效期内翻转实现,也就是二分频,同时也作为o_spi_clk。

当输入的命令为良品检测时,r_run信号将延迟拉低,具体时间为24bit的地址周期,加上56bit的读数据周期,最终当 r_cnt计数到88时在拉低,其余信号逻辑不变。

代码中的i_spi_8bit_cmd信号是上层模块输入的判断是否是良品检测命令,不是为1是为0。

复制代码
always@(*)
begin
	if(i_rst)
		r_spi_fsm_next	<=	'd0	;
	else begin
		case (r_spi_fsm_current)
			IDLE		:	
				if (w_user_active)	begin
					r_spi_fsm_next	<=	SPI_CMD	;
				end else 
					r_spi_fsm_next	<=	IDLE	;
			SPI_CMD		:
				if (r_cnt == 'd7 && r_spi_cnt)
					if (i_spi_8bit_cmd)
						r_spi_fsm_next	<=	SPI_END	;
					else 
						r_spi_fsm_next	<=	SPI_ADDR	;
				else 
					r_spi_fsm_next	<=	SPI_CMD		;
			SPI_ADDR	:
				if (r_cnt == 'd23 && r_spi_cnt)
					r_spi_fsm_next	<=	SPI_DATA	;
				else 
					r_spi_fsm_next	<=	SPI_ADDR	;
			SPI_DATA	:
				if (r_cnt == 'd55 && r_spi_cnt)
					r_spi_fsm_next	<=	SPI_END	;
				else 
					r_spi_fsm_next	<=	SPI_DATA	;
			SPI_END		:
				r_spi_fsm_next	<=	IDLE	;
			default		:
				r_spi_fsm_next	<=	IDLE	;
		endcase 
	end 
end 

always@(posedge i_clk,posedge i_rst)
begin
	if(i_rst)	
		r_run <= 'd0;
	else if (r_spi_fsm_current == SPI_CMD && i_spi_8bit_cmd)	begin
		if (r_spi_cnt && r_cnt == 'd7)
			r_run 	<=	1'b0;
		else 
			r_run	<=	1'b1;
	end else if (r_spi_fsm_current == SPI_DATA && r_run)	begin
		if (r_spi_cnt && r_cnt == 'd55)
			r_run	<=	1'b0	;
		else 
			r_run	<=	1'b1	;
	end else if(w_user_active)
		r_run <= 'd1;
	else 
		r_run <= r_run;
end

always@(posedge i_clk,posedge i_rst)
begin
	if(i_rst)
		r_cnt	<=	'd0	;
	else if (r_spi_fsm_current != r_spi_fsm_next)
		r_cnt <= 'd0;
	else if (r_run && r_spi_cnt)	
		r_cnt	<=	r_cnt + 'd1	;
end 

always@(posedge i_clk,posedge i_rst)
begin
	if(i_rst)
		r_spi_cnt <= 'd0;
	else if(r_run)
		r_spi_cnt <= r_spi_cnt + 1;
	else 
		r_spi_cnt <= 'd0;
end

对于6线spi芯片来说,它的数据线是inout接口,所以需要添加控制信号来判断是输入还是输出。如下代码,输出一下信号用于上层模块判断。

复制代码
(* PAP_MARK_DEBUG="1" *)wire    cmd_flag		=	(r_spi_fsm_current == SPI_CMD);
(* PAP_MARK_DEBUG="1" *)wire    addr_flag	=	(r_spi_fsm_current == SPI_ADDR);
(* PAP_MARK_DEBUG="1" *)wire    data_flag	=	(r_spi_fsm_current == SPI_DATA);

spi驱动模块的所有端口信号如下:

复制代码
spi_drive#(
    parameter               P_DATA_WIDTH        	= 8 ,
							P_ADDR_WIDTH		= 24,
							P_READ_DATA_WIDTH   	= 8 , 
							P_CPOL              	= 0 ,
							P_CPHL              	= 0 
)(                  
	input	wire					i_clk               ,
	input	wire					i_rst               ,

	output	wire					o_spi_clk           ,
	output	wire					o_spi_cs            ,
	
	input	wire					i_spi_mosi		,
	output 	wire					o_spi_miso		,
	output 	wire					o_spi_cmd_flag	,
	output 	wire					o_spi_addr_flag	,
	output 	wire					o_spi_data_flag	,

	input	wire					i_spi_8bit_cmd	,

	input	wire	[23:0]			i_user_addr			,
	input	wire	[7 :0]   		i_user_cmd        ,
	input	wire					i_user_valid        ,
	output	wire					o_user_ready        ,

    output	wire	[7:0]   		o_user_read_data    ,
    output	wire                    o_user_read_valid   
);

对于读取PSRAM读取良品检测输出信号,按照时序图我们需要在读数据阶段读到的第二个字节数据作为良品与否的判断。所以当r_cnt计数到15切r_qpi_cnt为1的时候获取读到的值。具体代码如下:

复制代码
always@(posedge ro_spi_clk,posedge i_rst)
begin
	if(i_rst)
		ro_user_read_data <= 'd0;
	else	if (data_flag)
		ro_user_read_data <= {ro_user_read_data[P_DATA_WIDTH - 2 : 0],i_spi_mosi};
	else 
		ro_user_read_data <= 'd0;
end

always@(posedge i_clk,posedge i_rst) 
begin
	if(i_rst)
		ro_user_read_valid <= 'd0;
	else if (r_spi_fsm_current == SPI_DATA && ((r_cnt == 'd7 || r_cnt == 'd15) && r_spi_cnt))
		ro_user_read_valid <= 'd1;
	else 
		ro_user_read_valid <= 'd0;
end

3.上板验证

按照时序图,关于spi驱动部分正确输出良品检测通过指令8'H5D。

相关推荐
FPGA-ADDA3 小时前
第一篇:软件无线电(SDR)基础与FPGA的角色
fpga开发·fpga·数字电路·dsp·软件无线电
Fpga_User7 小时前
基于Zynq UltraScale+的FLASH固化问题记录
嵌入式硬件·fpga开发
FPGA-ADDA7 小时前
高速数据记录仪19EG_4NVME_EXT_V1.2存储板
fpga开发·fpga·高速存储·mpsoc·大容量存储
Saniffer_SH7 小时前
【每日一题】PCIe链路协商的时候进入Polling compliance如何排错?
服务器·人工智能·驱动开发·嵌入式硬件·测试工具·fpga开发·自动化
亮锅锅来啦8 小时前
Synplify_2023综合时报错clk_out is not input pin
fpga开发
浩子智控8 小时前
航天高可靠性设备开发—抗辐射
嵌入式硬件·fpga开发·硬件工程
XPii8 小时前
FPGA工程师面试资料【1】
fpga开发·面试·职场和发展
沐欣工作室_lvyiyi16 小时前
基于FPGA的电容测试仪设计与实现(论文+源码)
fpga开发·毕业设计·电容测试仪·电阻电容电感测试
GateWorld1 天前
FPGA内部模块详解之三 FPGA的“记忆细胞”——嵌入式块内存(Block RAM)
fpga开发·block ram