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

<= 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 <= SECTOR_ERASE;//扇区擦除指令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:beginif(send_done)begin//主机一个字节数据被发送完成flow_cnt <= flow_cnt + 1'd1;spi_end <= 1'b1;//结束第1次SPI通信endelseflow_cnt <= flow_cnt;end'd9:begin//停留在这个状态flow_cnt <= flow_cnt;enddefault:;endcaseendendendmodule
SPI扇区擦除顶层模块代码如下:
`timescale 1ns/1ns//时间单位/精度//扇区擦除module spi_sector_erase(// 系统接口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_1000;//字节地址wirespi_start ;//发送传输开始信号,一个高电平wirespi_end;//发送传输结束信号,一个高电平wire [7:0]data_send;//要发送的数据wire [7:0]data_rec;//接收到的数据wiresend_done ;//主机发送一个字节完毕标志wirerec_done ;//主机接收一个字节完毕标志//------------<例化模块>----------------------------------------------------------------//扇区擦除模块spi_sector_erase_ctrl#(.SECTOR_ADDR(SECTOR_ADDR),.PAGE_ADDR(PAGE_ADDR),.BYTE_ADDR(BYTE_ADDR)) spi_sector_erase_ctrl_inst(.sys_clk(sys_clk ),.sys_rst_n(sys_rst_n ),.send_done(send_done ),.spi_start(spi_start ),.spi_end(spi_end ),.data_send(data_send ));//SPI驱动spi_drive spi_drive_inst(.sys_clk(sys_clk ),.sys_rst_n(sys_rst_n ),.spi_start(spi_start ),.spi_end(spi_end ),.data_send(data_send ),.data_rec(data_rec ),.send_done(send_done ),.rec_done(rec_done ),.spi_miso(spi_miso ),.spi_sclk(spi_sclk ),.spi_cs(spi_cs),.spi_mosi(spi_mosi ));endmodule
2.3.3、及仿真结果
比较简单直接例化扇区擦除模块和仿真模型即可 。需要注意的是的扇区擦除需要等待的时间较长(3s),为了尽快完成仿真,我把这个等待参数改成了1s 。
//------------------------------------------------//--SPI驱动仿真--扇区擦除仿真//------------------------------------------------`timescale 1ns/1ns//时间单位/精度//------------<模块及端口声明>----------------------------------------module tb_spi_sector_erase();regsys_clk;regsys_rst_n ;wire spi_miso ;wire spi_sclk ;wire spi_cs;wire spi_mosi ;//------------<例化被测试模块>----------------------------------------//扇区擦除模块spi_sector_erase spi_sector_erase_inst(.sys_clk (sys_clk ),.sys_rst_n (sys_rst_n ),.spi_miso (spi_miso ),.spi_sclk (spi_sclk ),.spi_cs(spi_cs),.spi_mosi (spi_mosi ));//m25p16仿真模型m25p16memory (.c(spi_sclk ), .data_in(spi_mosi), .s(spi_cs), .w(1'b1), .hold(1'b1), .data_out(spi_miso)); //------------<设置初始测试条件>----------------------------------------initial beginsys_clk = 1'b0;//初始时钟为0sys_rst_n