基于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。

相关推荐
zlinear数据采集卡8 小时前
基准电压电路深度解析:从理论参数到ZLinear采集卡的精准参考实战
c语言·单片机·嵌入式硬件·fpga开发·自动化
ALINX技术博客16 小时前
【黑金云课堂】FPGA技术教程Vitis开发:PS端SD读写
fpga开发·vitis·sd读写
尤老师FPGA17 小时前
LVDS系列50:Xilinx Ultrascale系 ADC LVDS接口参考方法(十二)
fpga开发
zlinear数据采集卡17 小时前
模拟输入限流保护电路深度解析:从理论原理到ZLinear采集卡的实战设计
c语言·单片机·嵌入式硬件·fpga开发·自动化
Dillon Dong1 天前
【风电控制】FPGA采集Vdc的ADC增益系数解析——从数字码到实际电压的桥梁
算法·fpga开发·变流器·风电控制
ALINX技术博客1 天前
【黑金云课堂】FPGA技术教程FPGA基础:FIFO与Uart通信
fpga开发·uart·fpga·fifo
zlinear数据采集卡1 天前
定时器电路深度解析:从经典555到STM32定时器,从ZLinear采集卡的工程化设计实战
stm32·单片机·嵌入式硬件·fpga开发·自动化
逻辑诗篇1 天前
FT-M6678+JFM7VX690T互联调试
fpga开发
szxinmai主板定制专家1 天前
基于 ARM+FPGA精密多轴实时运动控制卡设计方案,适用于半导体设备等高精度领域(一)
arm开发·人工智能·嵌入式硬件·fpga开发·架构·语音识别
2301_809049422 天前
blog_vitis_platform_system_application
fpga开发