spi flash通用读写软IP
来源:互联网 发布:json用什么解析 编辑:程序博客网 时间:2024/06/05 10:55
spi flash通用读写模块,有两个模块,分别为spiflash控制模块和spi控制模块
spiflash控制模块RTL代码如下:
//功能描述//这是一个spiflash的控制程序//写选择(wr)和读选择(rd)一样时为空操作//写选择(wr)为1并且读选择(rd)为0时使用写模式,写模式下有数据命令的选择//写选择(wr)为0并且读选择(rd)为1时使用读模式//命令和数据的输入都是使用data_in//地址的输入是使用addr//目前能使用的只有写入8位的命令(通过data_in),写入数据(通过addr和data_in),读出8位数据(通过addr和data_out),时钟上升沿//使用时不用检测忙位,模块会自动进行检测//当完成读或者写时信号spifl_over会出现上升沿 //DO、Dio、cs、spi_clk_out对应spiflash的端口module spiflash_common(flash_clk,sys_rst,DO,wr,rs,rd,addr,data_in,data_out,cs,Dio,spiflash_over,spi_clk_out);input flash_clk;//flash的时钟input sys_rst;//复位input DO;//flash数据的串行输出口input wr;//写选择,为1时有效,为0时无效input rs;//读选择,为1时有效,为0时无效input rd;//数据命令选择,为1时为数据,为0时为命令input [23:0] addr;input [7:0] data_in;output [7:0] data_out;outputcs;output Dio;output spiflash_over;//操作完成信号(上升沿)output spi_clk_out;reg [7:0] data_out_r;reg cs_r;reg spiflash_over_r; assign data_out = data_out_r;parameter disenable= 8'b00000001;//状态机编码,使用独热玛,这是不使能状态parameter open_wel = 8'b00000010;//打开写使能状态parameter write_com = 8'b00000100;//写命令状态parameter chip_program= 8'b00001000;//芯片编程状态,就是写数据parameter done = 8'b00010000;//完成状态parameter close_wel = 8'b00100000;//关闭写使能状态parameter read_data= 8'b01000000;//读数据状态parameter busy_check= 8'b10000000;//检测忙位状态reg [7:0] current_state/*synthesis noprune*/;reg [7:0] next_state;reg [1:0] check_busy_flag;wire busy;initial begincurrent_state = 8'd0;next_state = 8'd0;check_busy_flag = 2'd0;endwire input_check;assign input_check = wr ^ rd;//检测是否会读写冲突always@(posedge flash_clk or negedge sys_rst)//状态转移beginif(~sys_rst)current_state <= disenable;else if(input_check)current_state <= next_state;elsecurrent_state <= disenable;endreg [39:0] spi_data_out_r;reg [1:0] mode_r;always@(negedge flash_clk)//状态机begincase(current_state)disenable:begincs_r <= 1; //关闭片选spiflash_over_r <= 0;if(input_check)//检测是否读写冲突beginif(wr)beginnext_state <= busy_check;check_busy_flag <= 2'b00;//传到忙检测状态的标识码,以便检测到不忙时跳转到相应的状态endelsenext_state <= read_data;endelsenext_state <= disenable;endopen_wel:beginmode_r <= 2'b01;//传到spi控制器的模式选择,具体看spi控制器模块spi_data_out_r <= 40'h0000000006;//传到spi控制器的数据if(spi_over)//如果spi返回操作已经完成begincs_r <= 1;if(rs)next_state <= chip_program;elsenext_state <= write_com;endelsebegincs_r <= 0;next_state <= open_wel;endendwrite_com: beginmode_r <= 2'b01;spi_data_out_r <= {32'd0,data_in};check_busy_flag <= 2'b01;//传到忙检测状态的标识码,以便检测到不忙时跳转到相应的状态if(spi_over)begincs_r <= 1;next_state <= busy_check;endelsebegincs_r <= 0;next_state <= write_com;endendchip_program:beginmode_r <= 2'b11;spi_data_out_r <= {2'h02,addr,data_in};check_busy_flag <= 2'b10;if(spi_over)begincs_r <= 1;next_state <= busy_check;endelsebegincs_r <= 0;next_state <= chip_program;endendclose_wel:beginspi_data_out_r <= 40'h0000000004;mode_r <= 2'b01;if(spi_over)begincs_r <= 1;next_state <= done;spiflash_over_r <= 1;//操作已经完成,将spiflash_over拉高endelsebegincs_r <= 0;next_state <= close_wel;endendread_data:beginspi_data_out_r <= {8'h03,addr,8'h00};mode_r <= 2'b00;if(spi_over)begincs_r <= 1;data_out_r <= state_reg;next_state <= done;spiflash_over_r <= 1;//操作已经完成,将spiflash_over拉高endelsebegincs_r <= 0;next_state <= read_data;endendbusy_check:beginif(spi_over)begincs_r <= 1;if(busy)next_state <= busy_check;else beginif(check_busy_flag == 2'b00)//根据不同的标识码跳转的不同的状态next_state <= open_wel;else if(check_busy_flag == 2'b10)//根据不同的标识码跳转的不同的状态next_state <= close_wel;else beginnext_state <= done;spiflash_over_r <= 1;//操作已经完成,将spiflash_over拉高endendendelsebegincs_r <= 0;mode_r <= 2'b10; spi_data_out_r <= 40'h0000000500; next_state <= busy_check;endenddone:next_state <= disenable;//跳转到非使能状态,在这个状态中保持spiflash_over的高电平,否则如果直接跳转到非使能状态会立刻拉低spiflash_over,造成错误default: next_state <= disenable;endcaseendwire [1:0] mode;wire [39:0] spi_data_out;wire spi_over;wire [7:0]state_reg;spi_controller u1(.spi_clk_in(flash_clk),.mode (mode),.data(spi_data_out),.cs(cs),.miso(DO),.state_reg(state_reg),.mosi(mosi),.spi_over(spi_over),.spi_clk_out (spi_clk_out));assign Dio = mosi;assign cs = cs_r;assign spi_data_out = spi_data_out_r;assign mode = mode_r; assign spiflash_over= spiflash_over_r;assign busy = state_reg[0];endmodule
spi控制模块代码如下:
<pre name="code" class="plain">module spi_controller(spi_clk_in,mode,data,cs,miso,state_reg,mosi,spi_over,spi_clk_out);input spi_clk_in;//spi时钟的输入input [1:0] mode;//模式选择,有四个模式,00位读数据模式{8位读指令,24位地址,8位数据输出},01为输入8位命令,10为{8位读寄存器命令,8位寄存器数据输出},11为写数据模式{8位写命令,24位地址,8位数据输入}}input [39:0] data;//由上面的模式选择可以的到输入最多为40位的数据,输入数据用40位的位宽,如果用不到40位则只需用低位,如16位只用到40位的低16位input cs;//输入的片选端input miso;//flash的数据串行输出口output [7:0] state_reg;//状态寄存器的值output mosi;//flash的数据串行输入端output spi_over;//执行完成时标识信号,为0时为完成为1 时表示已经完成output spi_clk_out;//经过处理的spi时钟输出reg [5:0] spi_bit_num;reg spi_clk_out_flag;reg [5:0] spi_bit_counter;reg spi_over_r;always@(posedge spi_clk_in)begin case(mode)//对spi_bit_counter进行判断,如果已经操作完成,则给一个信号用于控制spi_clk_out,2'b00:begin spi_bit_num <= 41; spi_clk_out_flag <= (spi_bit_counter >= 40)?1:0; end//00模式,在40位的基础上加上一个周期给cs拉低到开始操作,和一个周期给停止操作到cs拉高2'b01:begin spi_bit_num <= 9; spi_clk_out_flag <= (spi_bit_counter >= 8)?1:0; end//01模式,同上2'b10:begin spi_bit_num <= 17; spi_clk_out_flag <= (spi_bit_counter >= 16)?1:0; end//10模式,同上2'b11:begin spi_bit_num <= 41; spi_clk_out_flag <= (spi_bit_counter >= 40)?1:0; end//11模式,同上default:begin spi_bit_num <= 0; spi_clk_out_flag <= 0; endendcaseendalways@(posedge spi_clk_in)beginif(cs) begin//如果没有被选中则清零spi_bit_counter <= 0;spi_over_r <= 0;endelse if(spi_over)//如果操作结束对进度计数器清零beginspi_bit_counter <= 0;endelse if(spi_bit_counter == spi_bit_num)//用于判断操作是否结束beginspi_bit_counter <= spi_bit_num;spi_over_r <= 1;endelsebeginspi_bit_counter <= spi_bit_counter + 1;//操作未结束时进度计数器自加spi_over_r <= 0;endendassign spi_clk_out = ((spi_bit_counter == 0) || (spi_clk_out_flag == 1)) ? 1 : spi_clk_in;//如果进度计数器是在0或者最大值,就是最小值和最大值,则时钟一直为1,否则就是spi时钟reg [39:0] data_r;reg mosi_r;always@(negedge spi_clk_out)//数据串行输出beginif(spi_over)mosi_r <= 0;elsecase(mode)//不同模式只取40位数据相应的位宽2'b00:mosi_r <= data_r[39];2'b01:mosi_r <= data_r[7];2'b10:mosi_r <= data_r[15];2'b11:mosi_r <= data_r[39];default:mosi_r <= 0;endcaseendalways@(posedge spi_clk_in)beginif(spi_bit_counter == 0)data_r <= data;//在进度为0时置数,将数据锁存进来else data_r <= data_r << 1;//随后开始右移,以满足总是取最高位给flash(上头的数据串行输出),简化设计endreg [7:0] state_reg_r;always@(posedge spi_clk_out)beginif((mode == 2'b10 && spi_bit_counter >= 9 && ~spi_over)||(mode == 2'b00 && spi_bit_counter >=33 && ~spi_over))//如果进度到了数据输出时开始更新寄存器数据state_reg_r <= {state_reg_r[6:0],miso};endassign state_reg = (spi_over)?state_reg_r:0;//操作完成时将数据输出assign mosi = mosi_r;assign spi_over = spi_over_r;endmodule
0 0
- spi flash通用读写软IP
- FLASH读写----SPI
- STM32 SPI接口读写SPI flash实验
- 读写SPI FLASH--驱动部分
- 读写SPI FLASH--应用程序部分
- LPC1343读写SPI FLASH at25f1024
- fpga的sdram通用读写软ip
- 基于FPGA的通用读写软IP
- STM32内部FLASH读写-通用
- ITE8502下的SPI flash读写问题
- STM32F10X SPI操作flash MX25L64读写数据
- STM32F10X SPI操作flash MX25L64读写数据
- sTM32F10X SPI操作flash MX25L64读写数据
- MX25L1635D spi-flash芯片的读写记录
- R8 STM32 SPI—读写串行 FLASH
- R8 STM32 SPI—读写串行 FLASH
- AVR(Mega8)的 IO口模拟SPI,读写FLASH
- 简述ich7中spi总线flash rom的读写
- [置顶] 一个简单的JAVA字符集过滤器实现 -vb2005xu 自己动手
- TabHost的简单实用
- 类的有参方法----------输入学生姓名及查找学生位置
- [置顶] 关于JAVA动态加载类[简单IOC的实现] -- vb2005xu自己动手
- 求参赛者的平均分,取最大值
- spi flash通用读写软IP
- [置顶] 在使用JS框架之前自己写的一些工具代码
- Structure from motion
- xUtils 中的HttpUtils源码解释
- org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter和org.apache.struts2.dispatcher.
- [置顶] 自己动手从源代码手动安装Python -- 搭建服务器Python 运行环境
- [置顶] 自己动手安装turbogears -- 搭建基本Python web开发服务器环境
- Android开发中Handler的经典总结
- txt文件导入mysql