SPI接口驱动模块设计
- 一、功能分析
- 二、状态机设计
- 三、信号说明
- 四、代码实现
- 五、仿真测试
写在前面:
FPGA实现SPI协议读写FLASH系列相关文章:
SPI通信协议
【FPGA】FPGA实现SPI协议读写FLASH(一)----- M25P16操作概述
在上篇文章中对FLASH(M25P16)读写操作及指令等做了详细介绍,本文将通过SPI协议原理,设计SPI通信接口,实现FPGA与FLASH进行通信。
本项目中所使用的开发板型号:Cyclone IV E (EP4CE6F17C8),FLASH型号:M25P16。
一、功能分析
SPI接口驱动模块(spi_interface)主要根据SPI协议原理架起FPGA与FLASH数据传输的“桥梁”,将从SPI读写控制模块接收到的指令、地址、数据字节严格按照SPI协议传输给FLASH,并接收从FLASH读回的数据,发送给SPI读写控制模块。
二、状态机设计
状态转移图如下:
状态说明:
IDLE:空闲状态,等待读写控制模块发起数据传输请求。
READY:准备传输数据。
TRANS:数据传输状态,根据SPI协议发送或接收数据。
DONE:数据传输结束。
三、信号说明
Port | I/O Type | Description |
---|---|---|
clk | input | 时钟信号 |
rst_n | input | 复位信号 |
req | input | 读/写数据请求 |
din[7:0] | input | 要传输给FLASH的数据 |
rdout[7:0] | output | 从FLASH读回的数据 |
rw_done | output | 读/写一字节数据完成标志 |
sclk | output | 同步时钟 |
cs_n | output | 片选信号 |
mosi | output | 主机输出,从机输入信号 |
miso | input | 主机输入,从机输出信号 |
四、代码实现
// **************************************************************
// Author: Zhang JunYi
// Create Date: 2022.11.15
// Design Name: spi_flash
// Module Name: spi_interface
// Target Device: Cyclone IV E (EP4CE6F17C8), FLASH(M25P16)
// Tool versions: Quartus Prime 18.1
// Description: SPI读写FLASH工程SPI接口模块
// **************************************************************
`include "param.v"
module spi_interface (
input clk ,
input rst_n ,
// flash_control
input req , // 读/写数据请求
input [7:0] din , // 要写入的数据
output [7:0] rdout , // 读回的数据
output rw_done , // 读写一字节数据完成标志
// M25P16
output sclk ,
output cs_n ,
output mosi ,
input miso
);
// 参数定义
localparam IDLE = 4'b0001 ,
READY = 4'b0010 ,
TRANS = 4'b0100 ,
DONE = 4'b1000 ;
// 信号定义
reg [3:0] state_c ;
reg [3:0] state_n ;
reg [4:0] cnt_sclk ; // sclk计数器
wire add_cnt_sclk ;
wire end_cnt_sclk ;
reg [4:0] cnt_bit ; // sclk计数器
wire add_cnt_bit ;
wire end_cnt_bit ;
reg sclk_reg ; // 输出sclk寄存
reg tx_data ; // 数据输出寄存
reg [7:0] rx_data ; // 读回数据寄存
// 状态转移条件
wire idle2ready ;
wire ready2trans ;
wire trans2done ;
wire done2idle ;
// 状态机
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state_c <= IDLE ;
end
else begin
state_c <= state_n ;
end
end
always @(*)begin
case (state_c)
IDLE: begin
if(idle2ready)
state_n = READY ;
else
state_n = state_c ;
end
READY: begin
if(ready2trans)
state_n = TRANS ;
else
state_n = state_c ;
end
TRANS: begin
if(trans2done)
state_n = DONE ;
else
state_n = state_c ;
end
DONE: begin
if(done2idle)
state_n = IDLE ;
else
state_n = state_c ;
end
default: state_n = IDLE ;
endcase
end
// 状态转移条件
assign idle2ready = state_c == IDLE && req ;
assign ready2trans = state_c == READY && (1'b1) ;
assign trans2done = state_c == TRANS && end_cnt_bit ;
assign done2idle = state_c == DONE && (1'b1) ;
// cnt_sclk
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_sclk <= 0 ;
end
else if(add_cnt_sclk)begin
if(end_cnt_sclk)begin
cnt_sclk <= 0 ;
end
else begin
cnt_sclk <= cnt_sclk + 1 ;
end
end
end
assign add_cnt_sclk = state_c == TRANS ;
assign end_cnt_sclk = add_cnt_sclk && (cnt_sclk == `SCLK_CYCLE - 1) ;
// sclk_reg
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sclk_reg <= 1'b1 ;
end
else if(add_cnt_sclk && cnt_sclk == `SCLK_FALL)begin
sclk_reg <= 1'b0 ;
end
else if(add_cnt_sclk && cnt_sclk == `SCLK_RISE)begin
sclk_reg <= 1'b1 ;
end
end
// cnt_bit
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bit <= 0 ;
end
else if(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <= 0 ;
end
else begin
cnt_bit <= cnt_bit + 1 ;
end
end
end
assign add_cnt_bit = end_cnt_sclk ;
assign end_cnt_bit = add_cnt_bit && (cnt_bit == 7) ;
// tx_data
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_data <= 1'b1 ;
end
else if(state_c == TRANS && cnt_sclk == `TRANS_S)begin
tx_data <= din[7 - cnt_bit] ;
end
else if(trans2done)begin
tx_data <= 1'b1 ;
end
end
// rx_data
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rx_data <= 0 ;
end
else if(state_c == TRANS && cnt_sclk == `SAMP_S)begin
rx_data[7 - cnt_bit] <= miso ;
end
end
// 输出
assign rdout = rx_data ;
assign rw_done = trans2done ;
assign sclk = sclk_reg ;
assign cs_n = ~req ;
assign mosi = tx_data ;
endmodule
五、仿真测试
SPI接口模块发送数据:
M25P16从机模型接收数据:
通过仿真分析,M25P16从机模型接收数据正确,SPI接口模块功能已实现。