DDR2/3 SDRAM学习笔记

这篇具有很好参考价值的文章主要介绍了DDR2/3 SDRAM学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

随路时钟概念

Dq(数据总线)与Dqs(时钟信号)构成随路时钟。
在Dqs上升或下降沿翻转Dq数据总线信号。
注意:dq与dqs为双线信号。两个信号都由发送方发送。dqs为数据同步信号。
随路时钟,学习,fpga开发
ODT引脚:片上终端电阻,数据线接上拉电阻。

DDR与DDR2区别

时钟

DDR外部IO时钟频率与内部存储时钟频率一致。
DDR2外部IO时钟是内部存储时钟频率的两倍。

片外驱动调校(OCD)

DDR2在初始化过程中配置模式寄存器前添加新EMRS选项:可选OCD功能。
目的是让DQS与DQ数据信号之间的偏差降低到最小。

片内终结(ODT)

DDR2:ODT功能让信号被电路的终端吸收,不会在电路上形成反射对后面信号造成影响。ODT将终结电阻移植到芯片内部。
随路时钟,学习,fpga开发

前置CAS、附加潜伏期、写入潜伏期

DDR2中读写指令可以紧随行激活发送,但读写操作没有提前,为了避免造成命令冲突,引入附加潜伏期。

RL(读潜伏期)= AL(附加潜伏期)+CL(列选通潜伏期)
从写入命令发出到第一个数据输入潜伏期  WL(写入潜伏期)=RL-1=AL+CL-1;
SDRAM无AL。

随路时钟,学习,fpga开发
tDQSS:发出写指令到写数据之间的时间。
随路时钟,学习,fpga开发

DDR2与DDR3区别

DDR3可以根据温度变化的自刷新频率。

参数

CL(寻址时序):DDR2 CL:2~5	  AL(附加延迟):0 ~4
			 DDR3 CL:5~11    AL(附加延迟): 0、CL-1、CL-2   CWD(写入延迟):由具体的工作频率而定

引脚

DDR3新增重置(Reset)功能: 初始化、重新配置模式寄存器。
ZQ: 该引脚通过命令集指令用相应的时钟周期对导通电阻和ODT电阻进行重新校准。

参考电压信号VREF

DDR3中,使用两个参考电压。VREFCA(命令与地址信号)、VREFDQ(数据总线)。

预读概念

bit (位)

			           突发长度		
DDR_SDRAM(2bit预读): 2   4   8	   内部结构导致,从内部总线32位中一次读出至少216位数据
DDR2_SDRAM(4bit预读) 4       8     一次至少读出416位,2个完整的时钟周期读出
DDR3_SDRAM(8bit预读)         8

使用突发长度时读写只能顺序地址;不使用读写长度时,读写地址可随机但是要连续写指令。
随路时钟,学习,fpga开发

随路时钟,学习,fpga开发

DDR3主要引脚

CK,CK_n:	差分信号时钟。
CKE:	高电平使能操作指令,低电平进入休眠自刷新状态。
CS_n:	片选使能信号。高电平使能芯片。 	 
RAS_n\CAS_n\WE_n:	指令输入。
DM(8位)/DMU,DML(16位):	遮掩输入数据使能信号。
BA0-BA2:	bank地址。
A10/AP:	使能在读写操作后自动预充电,高电平使能。
A0-A14(8位宽)/A0-A13(16位宽):	地址总线。
A21/BC_n:	默认高电平8bit突发长度,低电平使用突发突变模式(4bit读,4bit写)。
ODT: 	高/低电平使能校准功能。由芯片手册决定。  
RESET_n:	初始化或稳定工作中复位使能,重新配置模式寄存器。
DQ:		输入输出引脚,数据总线。
DQS,DQS_n(8位宽)/DQSL,DQSL_n,DQSU,DQSU_n(16位宽):	输入输出引脚,数据同步信号。
TDQS,TDQS_n(8位宽):		DRAMs输出引脚。数据遮掩信号,与DQS/DQS_n信号相同,在A11引脚控制下DM/TDQS_n可以使用数据遮掩,此时TDQS_n无效。
Vdd.Vddq:	电压引脚。
Vssq,Vss:	接地。
Vrefca:		CA参考电压。
 Vrefdq:	DQ参考电压。
 ZQ: 		该引脚通过命令集指令用相应的时钟周期对导通电阻和ODT电阻进行重新校准。

vivado IP核DDR3 SDRAM设置

随路时钟,学习,fpga开发
随路时钟,学习,fpga开发

PHY to Controller Clock Ratio:随路时钟,学习,fpga开发

DDR3读写实验

DDR3模块设计

随路时钟,学习,fpga开发

DDR3时序设计

随路时钟,学习,fpga开发

DDR3顶层模块代码

`timescale 1ns / 1ps

module ddr_top(
    input                 sys_clk,        //系统时钟						
    // DDR3			
    inout   [7:0]         ddr3_dq      ,  //DDR3 数据			
    inout   [0:0]         ddr3_dqs_n   ,  //DDR3 dqs负			
    inout   [0:0]         ddr3_dqs_p   ,  //DDR3 dqs正  			
    output  [14:0]        ddr3_addr    ,  //DDR3 地址   			
    output  [2:0]         ddr3_ba      ,  //DDR3 banck 选			
    output                ddr3_ras_n   ,  //DDR3 行选择			
    output                ddr3_cas_n   ,  //DDR3 列选择			
    output                ddr3_we_n    ,  //DDR3 读写选择			
    output                ddr3_reset_n ,  //DDR3 复位			
    output  [0:0]         ddr3_ck_p    ,  //DDR3 时钟正			
    output  [0:0]         ddr3_ck_n    ,  //DDR3 时钟负			
    output  [0:0]         ddr3_cke     ,  //DDR3 时钟使能			
    output  [0:0]         ddr3_cs_n    ,  //DDR3 片选			
    output  [0:0]         ddr3_dm      ,  //DDR3_dm			
    output  [0:0]         ddr3_odt        //DDR3_odt			
    );
	
wire					ui_clk				;	
wire					clk_200				;
wire					ui_clk_sync_rst		;
wire					init_done			;
wire		[28:0]		app_addr			;
wire		[2:0]		app_cmd				;
wire					app_en				;
wire		[63:0]		app_wdf_data		;
wire					app_wdf_end			;
wire					app_wdf_wren		;
wire		[63:0]		app_rd_data			;
wire					app_rd_data_end		;  
wire					app_rd_data_valid	;
wire					app_rdy				;
wire					app_wdf_rdy			;
wire		[31:0]		rd_addr_cnt			;
wire		[31:0]      wr_addr_cnt			;
wire					error_flog			;
wire					pll_locked			;
wire					data_state			;

	
reg						sys_rst				;
reg			[31:0]		time_cnt			;
wire					wr_en				;
wire                    rd_en               ;
wire					rst_en				;

always @(posedge clk_200)
	if(!pll_locked)
		time_cnt	<= 32'b0;
	else if(time_cnt == 32'd600_0)
		time_cnt <= time_cnt ;
	else 
		time_cnt <= time_cnt + 1'b1;

always @(posedge clk_200)
	if(!pll_locked)
		sys_rst	<= 1'b1;
	else if(time_cnt == 32'd600_0)
		sys_rst	<= 1'b0;
	else
		sys_rst	<= sys_rst;

  clk_wiz_0 PLL
   (

    .clk_out1(clk_200),     // output clk_out1

    .locked(pll_locked),       // output locked

    .clk_in1(sys_clk)
	);      // input clk_in1

vio_0 vio_0_inst (
  .clk(ui_clk),                // input wire clk
  .probe_in0(),    // input wire [0 : 0] probe_in0
  .probe_out0(wr_en),  // output wire [0 : 0] probe_out0
  .probe_out1(rd_en), // output wire [0 : 0] probe_out1
  .probe_out2(rst_en)  // output wire [0 : 0] probe_out2
);



ddr3_rw  ddr3_rw_inst(

    .ui_clk				(ui_clk)		,		//用户时钟 参考时钟		IP设置Clock Period 800M, 4:1比例ui_clk=200M (FPGA与DDR3传输数据时钟200M)
	.sys_rst			(ui_clk_sync_rst)         ,
	.rst_en				(rst_en),
	.init_done			(init_done)		,		//DDR3初始化完成
	.app_rdy			(app_rdy)			,		//IP核命令接收准备完成信号
	.app_wr_data_rdy	(app_wdf_rdy)		,		//IP核数据接受准备完成信号
	.app_rd_data_valid	(app_rd_data_valid)		,		//IP读数据有效
	.app_rd_data		(app_rd_data)			,		//mig读出的数据 		[63:0]	
	.wr_en				(wr_en)		,		//写使能
	.rd_en				(rd_en)		,		//读使能
                                             
	.app_addr			(app_addr)		,		//地址                  [28:0]	
	.app_en				(app_en)		,		//IP发送命令信号使能									
	.app_wd_wren		(app_wdf_wren)		 	,		//写数据使能
	.app_wd_end			(app_wdf_end)		,		//写突发当前时钟最后一个数据
    .app_cmd			(app_cmd)			,		//读写命令
    .app_data_wr		(app_wdf_data)			,		//写数据			[63:0]
    .rd_addr_cnt		(rd_addr_cnt)			,		//用户读地址计数	[31:0]
    .wr_addr_cnt		(wr_addr_cnt)			,	    //用户写地址计数    [31:0]
	.error_flog			(error_flog)		 	,    //读写错误标志
	.data_state			(data_state)	

);
 mig_7series_0 mig_7series_0_inst (

    .ddr3_addr                      (ddr3_addr),  // output [14:0]	
    .ddr3_ba                        (ddr3_ba),  // output [2:0]		
    .ddr3_cas_n                     (ddr3_cas_n),  // output		
    .ddr3_ck_n                      (ddr3_ck_n),  // output [0:0]	
    .ddr3_ck_p                      (ddr3_ck_p),  // output [0:0]	
    .ddr3_cke                       (ddr3_cke),  // output [0:0]	
    .ddr3_ras_n                     (ddr3_ras_n),  // output		
    .ddr3_reset_n                   (ddr3_reset_n),  // output		
    .ddr3_we_n                      (ddr3_we_n),  // output			
    .ddr3_dq                        (ddr3_dq),  // inout [7:0]		
    .ddr3_dqs_n                     (ddr3_dqs_n),  // inout [0:0]	
    .ddr3_dqs_p                     (ddr3_dqs_p),  // inout [0:0]	
    .init_calib_complete            (init_done),  // output			
	.ddr3_cs_n                      (ddr3_cs_n),  // output [0:0]	
    .ddr3_dm                        (ddr3_dm),  // output [0:0]		
    .ddr3_odt                       (ddr3_odt),  // output [0:0]		
    // Application interface ports
    .app_addr                       (app_addr),  // input [28:0]		
    .app_cmd                        (app_cmd),  // input [2:0]		
    .app_en                         (app_en),  // input				
    .app_wdf_data                   (app_wdf_data),  // input [63:0]		
    .app_wdf_end                    (app_wdf_end),  // input				
    .app_wdf_wren                   (app_wdf_wren),  // input				
    .app_rd_data                    (app_rd_data),  // output [63:0]		
    .app_rd_data_end                (app_rd_data_end),  // output			//突发读当前时钟最后一个数据 
    .app_rd_data_valid              (app_rd_data_valid),  // output			
    .app_rdy                        (app_rdy),  // output			
    .app_wdf_rdy                    (app_wdf_rdy),  // output			
    .app_sr_req                     (1'b0),  // input			该输入被保留并且应该被绑定到0。
    .app_ref_req                    (1'b0),  // input			该高电平有效输入请求向DRAM发出刷新命令。
    .app_zq_req                     (1'b0),  // input			该高电平有效输入请求向DRAM发出ZQ校准命令。
    .app_sr_active                  (),  // output			该输出保留。
    .app_ref_ack                    (),  // output			该输出保留。
    .app_zq_ack                     (),  // output			该输出保留。
    .ui_clk                         (ui_clk),  // output		200M	
    .ui_clk_sync_rst                (ui_clk_sync_rst),  // output			
    .app_wdf_mask                   (8'b0),  // input [7:0]		
    // System Clock Ports
    .sys_clk_i						(clk_200),			//Input Clock Period设置200M,ip核输入200M时钟。	
    .sys_rst                        (!sys_rst) // input 
	
);

endmodule

DDR3读写模块代码

`timescale 1ns / 1ps
module	ddr3_rw(
    input								ui_clk						,		//用户时钟 参考时钟
	input								sys_rst                         ,
	input								rst_en						,
	input								init_done					,		//DDR3初始化完成
	input								app_rdy						,		//IP核命令接收准备完成信号
	input								app_wr_data_rdy				,		//IP核数据接受准备完成信号
	input								app_rd_data_valid			,		//IP读数据有效
	input			[63:0]				app_rd_data					,		//mig读出的数据 		[63:0]	
	input								wr_en						,		//写使能
	input								rd_en						,		//读使能
	
				                                                                                            
	output		reg	[28:0]				app_addr					,		//地址                  [28:0]	
	output								app_en						,		//IP发送命令信号使能									
	output								app_wd_wren				 	,		//写数据使能
	output								app_wd_end					,		//写突发当前时钟最后一个数据
    output								app_cmd						,		//读写命令
    output		reg	[63:0]				app_data_wr					,		//写数据			[63:0]
    output		reg	[31:0]				rd_addr_cnt					,		//用户读地址计数	[31:0]
    output		reg	[31:0]				wr_addr_cnt					,	    //用户写地址计数    [31:0]
	output		reg						error_flog					,	    //读写错误标志
	output		reg						data_state
    );
	parameter DATA_LENGTH = 32'd1000;
	parameter IDLE =	3'b000;
	parameter WRITE = 3'b001;
	parameter WAIT = 3'b010;
	parameter READ = 3'b100;
	
	reg				[2:0]			state	;								//读写状态
	reg				[25:0]			rd_cnt	;								//实际读数据标记
	wire			rst						;
	reg				error					;
	
ila_0 ila_0_inst (
	.clk(ui_clk), // input wire clk
.probe0({init_done,app_rdy,app_rd_data_valid,app_rd_data,app_addr,app_en,app_wd_wren,app_wd_end,error_flog,data_state,app_data_wr,rd_cnt,app_wr_data_rdy,app_cmd,state,wr_en,rd_en,wr_addr_cnt,rd_addr_cnt,rst_en,sys_rst,rst,error}) // input wire [399:0] probe0
);

assign	rst	= rst_en | sys_rst;

assign	app_en	= (((state == WRITE)&&(app_wr_data_rdy&&app_rdy)) ||((state == READ)&&app_rdy)) ? 1'b1:1'b0;
assign	app_wd_wren	= ((state == WRITE)&&(app_wr_data_rdy&&app_rdy)) ? 1'b1:1'b0;
assign	app_wd_end	= app_wd_wren	;
assign	app_cmd	= (state == READ) ? 1'b1:1'b0;

always @(posedge ui_clk or posedge rst)
	if(rst || error_flog)
		begin
			state	<= IDLE;
			wr_addr_cnt	<= 	32'd0;
			rd_addr_cnt	<= 	32'd0;
			app_addr	<=	29'd0;
			app_data_wr	<=  64'b0;
			data_state	<=	1'b0 ;
		end
	else	if(init_done)
		begin
			case(state)
			
				IDLE	:
					begin
						if(wr_en)
							begin
								state	<=	WRITE	;													
							end
						else 
							begin
								state	<= IDLE	;
								wr_addr_cnt	<= 	32'd0;
								rd_addr_cnt	<= 	32'd0;
								app_addr	<=	29'd0;
								app_data_wr	<=  64'b0;
								data_state	<=	1'b0 ;								
							end

					end
					
				WRITE	:
					begin
						if(wr_addr_cnt == DATA_LENGTH - 1'b1)
							state <= WAIT	;
					else
						if(app_wr_data_rdy && app_rdy)
							begin
								wr_addr_cnt <= wr_addr_cnt + 1'b1;
								app_addr	<= app_addr + 29'd8;
								app_data_wr	<= app_data_wr	+ 1'b1;
								data_state	<=	1'b1 ;
							end
					else
						begin
							wr_addr_cnt <= wr_addr_cnt;
						    app_addr	<= app_addr ;
						    app_data_wr	<= app_data_wr;
							data_state	<=	data_state ;
						
						end					
					end
					
				WAIT	:
					begin
						if(rd_en)
							begin
								state <= READ;
								app_addr <=  29'b0;							
							end
						else
							begin
								state <= WAIT;
							    app_addr <=  app_addr;
							
							end
					end
					
				READ	:
					begin
						if(rd_addr_cnt == DATA_LENGTH - 1'b1)
							state <= IDLE ;
						else if(app_rdy)
							begin
								rd_addr_cnt <= rd_addr_cnt + 1'b1;
								app_addr	<= app_addr	+ 29'd8;
							end
						else
							begin
								rd_addr_cnt <= rd_addr_cnt ;
								app_addr	<= app_addr	;							
							end
					end
	
				default	:
					begin
						state	<= IDLE;
						wr_addr_cnt	<= 	32'd0;
						rd_addr_cnt	<= 	32'd0;
						app_addr	<=	29'd0;
						data_state	<=	data_state ;
					end
			endcase

		end
		
always @(posedge ui_clk or posedge rst)
	if(rst)
		rd_cnt <= 26'd0;
	else if(app_rd_data_valid)
		begin
			if(rd_cnt == DATA_LENGTH - 1'b1)
				rd_cnt <= 26'd0;
			else
				rd_cnt <= rd_cnt + 1'b1;		
		end
	else
		rd_cnt <= rd_cnt;	
		
always @(posedge ui_clk or posedge rst)
	if(rst)
		error_flog <= 1'b0;
	else if((state == READ) && app_rd_data_valid)
		begin
			if(rd_cnt != app_rd_data)
				error_flog <= 1'b1;
			else
				error_flog <= 1'b0;		
		end
	else
		error_flog <= 1'b0;	

always @(posedge ui_clk or posedge rst)
	if(rst)
		error <= 1'b0;
	else if(error_flog)
		error <= 1'b1;
	else 
		error <= error;
		
endmodule

DDR3读写实际波形

使用逻辑分析仪查看DDR3写时序。
随路时钟,学习,fpga开发使用逻辑分析仪查看DDR3读时序。
随路时钟,学习,fpga开发

DDR4 IP 时钟

随路时钟,学习,fpga开发

vivado IP核PLL设置

随路时钟,学习,fpga开发
随路时钟,学习,fpga开发
随路时钟,学习,fpga开发

X16 DDR4芯片引脚选址

随路时钟,学习,fpga开发
地址/控制引脚:cs_n,ras_n,we_n等。
字节通道分为T0,T1,T2,T3。每个通道分两小组U和L。
随路时钟,学习,fpga开发
随路时钟,学习,fpga开发

X16和X8型号的dqs:必须在U通道上,必须在N6/N7。
dq:不能在N1,N12,但与dps在同一通道。
随路时钟,学习,fpga开发
dm/dbi:与dqs在同一通道线且只能在N0。
随路时钟,学习,fpga开发

随路时钟,学习,fpga开发
一个Bank只能绑定一组DQ。
随路时钟,学习,fpga开发
reset_n:任何引脚但IO standard必须满足LVCMOS12。
dq低位对应P。高位对应N。dq[0]:p dq[1]:N文章来源地址https://www.toymoban.com/news/detail-521609.html

到了这里,关于DDR2/3 SDRAM学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA应用学习笔记--时钟域的控制 亚稳态的解决

    时钟域就是同一个时钟的区域,体现在laways语句边缘触发语句中,设计规模增大就会导致时钟不同步,有时差,就要设计多时钟域。  会经过与门的延时产生的新时钟域,这种其实不推荐使用,但在ascl里面很常见 在处理时钟域的信号传递,一般会有故障具有随机性,不同工

    2024年02月13日
    浏览(39)
  • DDR4 SDRAM (MIG) IP 核用法

    我们只需关注与IP核交互的部分信号即可,IP核与DDR4交互的部分不用关心。下图框出的部分即需要关注的信号。 框起来的信号的详细用法,具体可以参考官方给的 example design,此文章主要总结用法,可能并不详细。 关于写: c0_ddr4_app_wdf_wren= 1 时数据写入DDR, 数据写入成功必须

    2024年02月11日
    浏览(44)
  • FPGA开发-ddr测试

    文章目录 概要 整体架构流程 技术名词解释 技术细节 小结 提示:这里可以添加技术概要 例如: 本文以米联科开发板为例,介绍ddr测试相关例程。 提示:这里可以添加技术整体架构 提示:这里可以添加技术名词解释 例如: app _addr:表示正在提交给用户界面的请求的地址。聚

    2024年02月08日
    浏览(41)
  • 基于 A7 的 DDR3 SDRAM IP 核使用(二)初始化篇

    前言 :在前文简单介绍了MIG ip核的调用(包括某些参数的设置)以及该ip核的架构。那么接下来可以开始使用ip核了吗?NO!!! 注意 :在调完ip之后,并不可以立即使用该 IP 核完成 DDR3 SDRAM 的读和写的,而是要在该 IP核初始化成功之后 ,才可以进行读和写的。 可以通过 Models

    2024年02月04日
    浏览(32)
  • FPGA实战开发-基于DDR的图像缓存(下)

    文章目录 概要 整体架构流程 技术名词解释 技术细节 小结 例如: 基于米联科的学习资料,分享和学习同步,欢迎大家一起探讨。 提示:这里可以添加技术整体架构 例如:       image_data_gen产生了测试图片,之后进入过W0 FIFO进行视频缓存。每次缓存1024个像素,就往通过F

    2024年02月17日
    浏览(39)
  • FPGA实战开发-基于的ddr图像缓存设计(上)

    目录 概要 整体架构流程 技术名词解释 技术细节 ​编辑 小结 提示:这里可以添加技术概要 本文主要基于DDR的图像缓存设计。 提示:这里可以添加技术整体架构 先用图像产生模块产生一个1080P60Hz的测试图像,然后经过FDMA进入ddr3,缓存3帧后在读出来。然后在经过HDMI显示。

    2024年02月08日
    浏览(61)
  • itop-3568开发板驱动学习笔记(24)设备树(三)时钟实例分析

    《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 设备树中的时钟信息以时钟树形式体现,时钟树包括时钟的属性和结构等信息,驱动在进行时钟初始化时,会从设备树中获取对应的时钟参数。 在设备树中,时钟分为消费者和生产者。 #clock-cells 代表时钟的路数,

    2024年02月01日
    浏览(33)
  • FPGA学习笔记-1 FPGA原理与开发流程

    注:笔记主要参考: B站 正点原子 教学视频“正点原子手把手教你学FPGA-基于达芬奇Pro开发板 Artix-7 XC7A35T/XC7A100T”。 小梅哥爱漂流 教学视频“【零基础轻松学习FPGA】小梅哥Xilinx FPGA基础入门到项目应用培训教程”。 B站搬运 “特权同学2020版《深入浅出玩转FPGA视频教程》

    2024年02月05日
    浏览(50)
  • 紫光同创 FPGA 开发跳坑指南(四)—— DDR3 控制器 IP 的使用

    DDR3 是一种大容量的存储器件,采用了预取技术和双边沿采样技术,以实现高速数据存储与读取,在视频处理中可以用来缓存 1 帧或多帧图像。 目录 一、紫光 DDR3 IP 的安装 二、紫光 DDR3 IP 的配置 三、DDR3 IP 的使用 3.1 DDR3 写操作 3.2 DDR3 读操作         在 Pango Design Suit 中,选

    2024年01月25日
    浏览(49)
  • FPGA学习——FPGA实现电子时钟

    Cyclone IV开发板上的数码管一共有6个,我们每次只能选择其中一个显示,怎么解决电子时钟时、分、秒同时显示呢?要实现电子时钟首先要了解什么是余晖效应。   余晖效应一般指视觉暂留。 视觉暂留现象即视觉暂停现象(Persistence of vision,Visual staying phenomenon,duration o

    2024年02月09日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包