2 FPGA实现SPI接口--SPI接口芯片的实际使用( 二 )


页写时序如下:
2.1.2、代码
代码分为3个模块:SPI驱动模块、SPI页写控制模块l和页写顶层模块 。
SPI页写控制模块l代码如下:
//SPI页写控制模块`timescale 1ns/1ns//时间单位/精度module spi_page_program_ctrl#(parameterSECTOR_ADDR = 8'b0000_0000,//扇区地址parameter PAGE_ADDR= 8'b0000_0000,//页地址parameter BYTE_ADDR= 8'b0000_0000//字节地址)(inputsys_clk,// 全局时钟50MHzinputsys_rst_n ,// 复位信号,低电平有效inputsend_done ,// 主机发送一个字节完毕标志位outputregspi_start ,// 发送传输开始信号,一个高电平outputregspi_end,// 发送传输结束信号,一个高电平outputreg[7:0]data_send// 要发送的数据);//指令定义localparamWR_EN= 8'b0000_0110,//写使能指令 PAGE_PROGRAM = 8'b0000_0010;//页写指令localparam DATA_MAX= 8'd10;//最大数据写入个数//reg definereg [7:0] flow_cnt;//状态跳转计数器reg [7:0] cnt_wait;//上电等待计数器reg [7:0] data_cnt;//数据写入个数计数器always@(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)begindata_send <= 8'd0;spi_start <= 1'b0; spi_end <= 1'b0; flow_cnt <= 1'd0;cnt_wait <= 8'd0;data_cnt <= 8'd0;endelse beginspi_start <= 1'b0;//便于生成脉冲信号spi_end <= 1'b0;//便于生成脉冲信号case(flow_cnt)'d0:beginif(cnt_wait == 100)begin//上电后等待稳定cnt_wait <= 8'd0;flow_cnt <= flow_cnt + 1'd1;endelse begincnt_wait <= cnt_wait + 1'd1;flow_cnt <= flow_cnt;endend'd1:begindata_send <= WR_EN;//写使能指令spi_start <= 1'b1;//拉高spi开始通讯信号flow_cnt <= flow_cnt + 1'd1;end'd2:beginif(send_done)begin//主机一个字节数据被发送完成flow_cnt <= flow_cnt + 1'd1;spi_end <= 1'b1;//结束第1次SPI通信endelseflow_cnt <= flow_cnt;end 'd3:beginif(cnt_wait == 10)begin//等待200ns,两次命令的间隔时间cnt_wait <= 8'd0;//等待计数器清零flow_cnt <= flow_cnt + 1'd1;endelse begincnt_wait <= cnt_wait + 1'd1;flow_cnt <= flow_cnt;endend'd4:begindata_send <= PAGE_PROGRAM;//页写指令spi_start <= 1'b1;//拉高spi开始通讯信号flow_cnt <= flow_cnt + 1'd1;end'd5:begin//发送扇区地址if(send_done)begin//指令被发送完成flow_cnt <= flow_cnt + 1'd1;data_send <= SECTOR_ADDR;//数据为扇区地址endelse beginflow_cnt <= flow_cnt;data_send <= data_send;endend 'd6:begin//发送页地址if(send_done)begin//发送完成flow_cnt <= flow_cnt + 1'd1;data_send <= PAGE_ADDR;//数据为页地址地址endelse beginflow_cnt <= flow_cnt;data_send <= data_send;endend 'd7:begin//发送字节地址if(send_done)begin//指令被发送完成flow_cnt <= flow_cnt + 1'd1;data_send <= BYTE_ADDR;//数据为字节地址endelse beginflow_cnt <= flow_cnt;data_send <= data_send;endend 'd8:begin//停留在这个状态if(send_done)begin//指令被发送完成flow_cnt <= flow_cnt + 1'd1;data_send <= 8'd0;//发送数据从0开始end else flow_cnt <= flow_cnt;end'd9:begin//写入数据if(send_done)begin//主机一个字节数据被发送完成if(data_cnt == DATA_MAX - 1'b1)begin //数据全部写入flow_cnt <= flow_cnt + 1'd1;spi_end <= 1'b1;//结束第1次SPI通信data_cnt <= 8'd0;data_send <= 8'd0;endelse beginflow_cnt <= flow_cnt;data_cnt <= data_cnt + 8'd1;//计数器累加1 // data_send <= data_send + 8'd2; //数据累加2 data_send <= data_send + 8'd4;//数据累加4 endendelse beginflow_cnt <= flow_cnt;data_send <= data_send;data_cnt <= data_cnt;endend'd10:begin//停留在这个状态flow_cnt <= flow_cnt;enddefault:;endcaseendendendmodule
页写顶层模块代码如下:
`timescale 1ns/1ns//时间单位/精度//页写module spi_page_program(// 系统接口input sys_clk,//全局时钟50MHzinput sys_rst_n ,//复位信号,低电平有效// SPI物理接口input spi_miso ,//SPI串行输入,用来接收从机的数据output spi_sclk ,//SPI时钟output spi_cs,//SPI片选信号,低电平有效output spi_mosi//SPI输出,用来给从机发送数据);parameterSECTOR_ADDR = 8'b0000_0000;//扇区地址parameter PAGE_ADDR= 8'b0000_0000;//页地址parameter BYTE_ADDR= 8'b0000_0000;//字节地址wirespi_start ; //发送传输开始信号,一个高电平wirespi_end;//发送传输结束信号,一个高电平wire [7:0]data_send;//要发送的数据wire [7:0]data_rec;//接收到的数据wiresend_done ;//主机发送一个字节完毕标志wirerec_done ;//主机接收一个字节完毕标志//------------