基于FPGA的SD卡写数据Verilog程序开发

1.仿真预览

操作步骤,先格式化。设置如下:

注意,格式化之后,使用容量如下:

假如我在文档中保存一个数据

里面数据为1

此时容量使用变为:

根据这个信息,我们最后来验证写入的数据量是否正确。

然后使用我新的下载程序,运行后,再次打开,可以看到如下:

按原来的程序,下载后, 其容量为

并提示格式化。

然后按我的新程序,得到结果如下:

数据已经被写入了,由于我们写入的是bit数据,不是实际的声音或者视频,所以没法看到文件形式,这个需要借助软件查看,具体操作如下:

使用我提供给你的这个软件。

File>打开路径。定位到你的SD卡物理路径,然后点击

,然后点击。定位到偏移地址位置。

具体看录像中显示效果。

然后这个软件也显示了

使用空间大小。

假如我对SD卡格式化,重复上面的操作,结果如下所示:

具体看录像中显示效果。

这样的话,就读写成功了。

2.部分核心代码

`timescale 1ns / 1ps
//
// Module Name:    sd_write 
//
module sd_write(  input SD_clk,
						output reg SD_cs,
						output reg SD_datain,
						input  SD_dataout,
						
						input init,
						
						input [31:0] sec,            //写SD的sec地址
						input write_req,             //写SD卡请求
						
						output reg [3:0] mystate,
						
						output reg rx_valid,         
						
						output reg write_o
						
						
    );
	 
	 
parameter idle=4'd0;
parameter write_cmd=4'd1;
parameter wait_8clk=4'd2;
parameter start_taken=4'd3;
parameter writea=4'd4;
parameter write_crc=4'd5;
parameter write_wait=4'd6;
parameter write_done=4'd7;	 
	 
//定义要写入的数据
wire[7:0]DATAIN;
assign DATAIN = 8'h3f;//可以随便定义	 
	 
wire [3:0] mystate_o;

reg [7:0] rx;

reg en;

reg [5:0] aa;	 
reg [21:0] cnt;

reg [7:0] write_data;

reg [47:0] CMD24={8'h58,8'h00,8'h00,8'h00,8'h00,8'hff};//block写命令CMD24的字节序列
reg [7:0] Sblock_token=8'hfe;                  //令牌字

reg [7:0] CMDX;
reg [7:0] CMDY=8'hff;
reg [2:0] cnta;


	 
always @(posedge SD_clk)
begin
	rx[0]<=SD_dataout;
	rx[7:1]<=rx[6:0];
end

//接收SD卡的应答数据
always @(posedge SD_clk)
begin
	if(!SD_dataout&&!en)begin rx_valid<=1'b0; aa<=1;en<=1'b1;end      //等待SD_dataout为低,SD_dataout为低,开始接收数据
   else if(en)	begin 
		if(aa<7) begin
			aa<=aa+1'b1; 
			rx_valid<=1'b0;
		end
		else begin
			aa<=0;
			en<=1'b0;
			rx_valid<=1'b1;             //接收完第8bit后,rx_valid信号开始有效
		end
	end
	else begin en<=1'b0;aa<=0;rx_valid<=1'b0;end
end

//SD卡写程序
always @(negedge SD_clk)
if(!init)
	begin
		mystate<=idle;
		CMD24<={8'h58,8'h00,8'h00,8'h00,8'h00,8'hff};
		write_o<=1'b0;
	end
else
	begin
	case(mystate)
		idle:	begin
				SD_cs<=1'b1;
				SD_datain<=1'b1;
				cnt<=22'd0;			
				if(write_req) begin          //如果有写请求			
						mystate<=write_cmd;
						CMD24<={8'h58,sec[31:24],sec[23:16],sec[15:8],sec[7:0],8'hff};
						Sblock_token<=8'hfe;
						write_o<=1'b0;
					end
				else mystate<=idle;
		end
		write_cmd: begin                    //发送CMD24命令 (single Block write)	
			   if(CMD24!=48'd0) begin
					SD_cs<=1'b0;
					SD_datain<=CMD24[47];
					CMD24<={CMD24[46:0],1'b0};     //移位输出,高位在先						
				end
				else begin 
				   if(rx_valid) begin         //等待应答信号			
						cnta<=7;
						mystate<=wait_8clk;
						SD_cs<=1'b1;
					   SD_datain<=1'b1;					
					end
				end
		end
		wait_8clk: begin                     //写数据之前等待8clock
			 if(cnta>0) begin
					 cnta<=cnta-1'b1;
					 SD_cs<=1'b1;
					 SD_datain<=1'b1;
			 end
			 else begin
					 SD_cs<=1'b1;
					 SD_datain<=1'b1;
					 mystate<=start_taken;
					 cnta<=7;
			 end
		end		
		start_taken: begin             //发送Start Block Taken
			 if(cnta>0) begin
					 cnta<=cnta-1'b1;
					 SD_cs<=1'b0;
					 SD_datain<=Sblock_token[cnta];         //高位在先发送
			 end
			 else begin
					 SD_cs<=1'b0;
					 SD_datain<=Sblock_token[0];
					 mystate<=writea;
					 cnta<=7;
					 cnt<=0;
				end
		end
		writea: begin             //写字节到SD卡
				if(cnt<512)	begin		
			     if(cnta>0)	
				  begin
				  		SD_cs<=1'b0;
				      SD_datain<=DATAIN[cnta];
						cnta<=cnta-1'b1;
				  end
				  else begin
				  		SD_cs<=1'b0;
						SD_datain<=DATAIN[0];
						cnta<=7;
						cnt<=cnt+1'b1;
				  end
				end
				else begin           

			     if(cnta>0)	begin
				      SD_datain<=DATAIN[cnta];
						cnta<=cnta-1'b1;
				  end
				  else begin
						SD_datain<=DATAIN[cnta];
						cnta<=7;
						cnt<=0;
					   mystate<=write_crc;						
				  end
 				end
		end
		write_crc: begin               //写crc:0xff,0xff
				if(cnt<16) begin
					 SD_cs<=1'b0;
					 SD_datain<=1'b1;
					 cnt<=cnt+1'b1;
				 end
				 else begin
				    if(rx_valid)         //等待Data Response Token
							mystate<=write_wait;
					 else
							mystate<=write_crc;					 
				end
		end
		write_wait: begin               //等待数据写入完成,
				if(rx==8'hff) begin
					mystate<=write_done;	 
				end
				else begin 
					mystate<=write_wait;
				end
		end
		write_done:begin
			  if(cnt<22'd15) begin      //等待15个clock
					SD_cs<=1'b1;
					SD_datain<=1'b1;
					cnt<=cnt+1'b1;
			  end
			  else begin
					mystate<=idle;
					write_o<=1'b1;	
               cnt<=0;
           end					
		end		
		default:mystate<=idle;
		endcase		
	end					
	

endmodule
`timescale 1ns / 1ps

module sd_test(
					input  clk,     //50Mhz input clock      
					input rst_n,
					
					output SD_clk,	    //25Mhz SD SPI时钟				
					output SD_cs,      //SD SPI片选	
					output SD_datain,  //SD SPI数据输入	
					input  SD_dataout,  //SD SPI数据输出	
					output led
					
    );
	 
	 
reg rst_n2=1'b0;
reg[31:0]cnt=32'd0;
always @(posedge clk)
begin
cnt<=cnt+32'd1;
if(cnt==32'h00ff_ffff)
rst_n2<=1'b1;
else
rst_n2<=rst_n2;
end

assign led=~rst_n2;


wire SD_datain_i;
wire SD_datain_w;
wire SD_datain_r;
reg  SD_datain_o;

wire SD_cs_i;
wire SD_cs_w;
wire SD_cs_r;
reg  SD_cs_o;



//PLL产生25Mhz的SD卡SPI时钟
pll pll_inst(
	.areset (~rst_n2),
	.inclk0 (clk),
	.c0     (SD_clk),
	.locked ()
	);




reg [31:0]read_sec;
reg read_req;

reg [31:0]write_sec;
reg write_req;

wire [7:0]mydata_o/* synthesis keep */;
wire myvalid_o/* synthesis keep */;

wire init_o/* synthesis keep */;             //SD 初始化完成标识
wire write_o;                                //SD blcok写完成标识
wire read_o;                                 //SD blcok读完成标识

reg [3:0] sd_state;

wire [3:0] initial_state;
wire [3:0] write_state;
wire [3:0] read_state;

wire rx_valid;

parameter STATUS_INITIAL=4'd0;
parameter STATUS_WRITE=4'd1;
parameter STATUS_READ=4'd2;
parameter STATUS_IDLE=4'd3;

assign SD_cs     = SD_cs_o;
assign SD_datain = SD_datain_o;


always @ ( posedge SD_clk or negedge rst_n2 )
    if( !rst_n2 ) 
	 begin
			sd_state  <= STATUS_INITIAL;
			read_req  <= 1'b0;
			read_sec  <= 32'd0;
			write_req <= 1'b0;
			write_sec <= 32'd0;			
	 end
	 else 
	     case( sd_state )

	      STATUS_INITIAL:
			if( init_o ) 
			begin 
			   sd_state  <= STATUS_WRITE; 
			   write_sec <= 32'd0; 
			   write_req <= 1'b1; 
			end
			else 
			begin 
			   sd_state <= STATUS_INITIAL; 
			end	
		  
	      STATUS_WRITE:
			if( write_o ) 
			begin 
			   sd_state <= STATUS_IDLE; 
			end
			else 
			begin 
			   write_req<= 1'b0; 
			   sd_state <= STATUS_WRITE; 
			end
			
			
	      STATUS_IDLE:   
			sd_state <= STATUS_IDLE;
			
			default: sd_state <= STATUS_IDLE;
	      endcase

			
			
//SD卡初始化程序				
sd_initial	sd_initial_inst(					
						.rst_n(rst_n2),
						.SD_clk(SD_clk),
						.SD_cs(SD_cs_i),
						.SD_datain(SD_datain_i),
						.SD_dataout(SD_dataout),
						.rx(),
						.init_o(init_o),
						.state(initial_state)

);


//write		 
sd_write	sd_write_inst(   
						.SD_clk(SD_clk),
						.SD_cs(SD_cs_w),
						.SD_datain(SD_datain_w),
						.SD_dataout(SD_dataout),
						
						.init(init_o),
						.sec(32'd16448),
						.write_req(write_req),
						.mystate(write_state),
						.rx_valid(rx_valid),

						.write_o(write_o)			
						
    );

	 

always @(*)
begin
	 case( sd_state )
	 STATUS_INITIAL: 
	 begin 
	 SD_cs_o<=SD_cs_i;
	 SD_datain_o<=SD_datain_i; 
	 end
	 
	 STATUS_WRITE: 
	 begin SD_cs_o<=SD_cs_w;
	 SD_datain_o<=SD_datain_w; 
	 end
	 
	 default: 
	 begin 
	 SD_cs_o<=1'b1;
	 SD_datain_o<=1'b1; 
	 end	 
	 
	 endcase
end


	 

endmodule

A38-11

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FPGASD卡Verilog设计逻辑Quartus工程源码文件,FPGA型号Cyclone4E系列中的EP4CE10F17C8,Quartus版本18.0。 module top_sd_rw( input sys_clk , //系统时钟 input sys_rst_n , //系统复位,低电平有效 //SD卡接口 input sd_miso , //SD卡SPI串行输入数据信号 output sd_clk , //SD卡SPI时钟信号 output sd_cs , //SD卡SPI片选信号 output sd_mosi , //SD卡SPI串行输出数据信号 //LED output [3:0] led //LED灯 ); //wire define wire clk_ref ; wire clk_ref_180deg ; wire rst_n ; wire locked ; wire wr_start_en ; //开始SD卡数据信号 wire [31:0] wr_sec_addr ; //数据扇区地址 wire [15:0] wr_data ; //数据 wire rd_start_en ; //开始SD卡数据信号 wire [31:0] rd_sec_addr ; //读数据扇区地址 wire error_flag ; //SD卡错误的标志 wire wr_busy ; //数据忙信号 wire wr_req ; //数据请求信号 wire rd_busy ; //读忙信号 wire rd_val_en ; //数据读取有效使能信号 wire [15:0] rd_val_data ; //读数据 wire sd_init_done ; //SD卡初始化完成信号 //***************************************************** //** main code //***************************************************** assign rst_n = sys_rst_n & locked; //锁相环 pll_clk u_pll_clk( .areset (1'b0 ), .inclk0 (sys_clk ), .c0 (clk_ref ), .c1 (clk_ref_180deg), .locked (locked ) ); //产生SD卡测试数据 data_gen u_data_gen( .clk (clk_ref), .rst_n (rst_n), .sd_init_done (sd_init_done), .wr_busy (wr_busy), .wr_req (wr_req), .wr_start_en (wr_start_en), .wr_sec_addr (wr_sec_addr), .wr_data (wr_data), .rd_val_en (rd_val_en), .rd_val_da
FPGASD卡音乐播放例程Verilog逻辑源码Quartus工程文件+文档说明,,FPGA型号Cyclone4E系列中的EP4CE6F17C8,Quartus版本17.1。 实验简介 在其他实验中我们已经完成了 SD 卡读和音频模块的录音播放,本实验通过搜索 SD 卡中 WAV 音乐文件,然后送到音频模块播放,完成一个简单音乐播放器的功能。 2 实验原理 本实验一个关键是在没有文件系统的情况下,搜索 SD 卡每个扇区的内容,匹配出 WAV 文件, 这里有一个假设:假设每一个文件都是从一个扇区第一个字节开始而且文件是连续存储的,经过 大量实验,发现 FAT32 文件格式中的文件确实如此。 2.1 WAV 文件格式 大部分的文件都有文件头,WAV 也丌例外,我们通过分析 SD 卡一个扇区的前几个字节,判 断这个文件是否为 WAV 文件。 WAV 文件作为多媒体中使用的声波文件格式之一,它是以 RIFF 格式为标准的。RIFF 是英文 Resource Interchange File Format 的缩,每个 WAV 文件的头四个字节便是“RIFF”,所以本实验 就简单的以每个扇区的前 4 个字节是否为“RIFF”判断该文件是否为 WAV 文件,紧接着 4 个字节 表示文件的大小,这样我们就可以确定要读取的数据量。WAV 文件头大小是 88 字节,在播放时 要把前 88 个字节的文件头去掉。 module top( input clk, input rst_n, input key1, input wm8731_bclk, //audio bit clock input wm8731_daclrc, //DAC sample rate left right clock output wm8731_dacdat, //DAC audio data output input wm8731_adclrc, //ADC sample rate left right clock input wm8731_adcdat, //ADC audio data input inout wm8731_scl, //I2C clock inout wm8731_sda, //I2C data output sd_ncs, //SD card chip select (SPI mode) output sd_dclk, //SD card clock output sd_mosi, //SD card controller data output input sd_miso, //SD card controller data input output [5:0] seg_sel, output [7:0] seg_data ); wire[9:0] lut_index; wire[31:0] lut_data; wire[3:0] state_code; wire[6:0] seg_data_0; //I2C master controller i2c_config i2c_config_m0( .rst (~rst_n ), .clk (clk ),

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fpga和matlab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值