FPGA学习笔记(十八)spi_flash模块代码

该文描述了一个SPI闪存模块的设计,包括50MHz时钟4分频得到12.5MHzSPI时钟的计数器,以及使用状态机进行数据传输的控制。在传输过程中,数据被存储在额外的寄存器以确保稳定性。状态机管理着不同的操作阶段,如等待使能、数据发送与接收,同时有一个忙标志用于指示传输是否完成。
摘要由CSDN通过智能技术生成

 模块端口共有9个,5个输入4个输出。输入分别为:时钟clk,复位rst,主输入从输出miso,片选rw,需要发送的数据data_out,输出分别有,主输出从输入mosi,spi时钟sclk,接收到的数据data_in,状态标志busy。

module spi_flash(
input clk,
input rst,
input miso,
input rw,
input [7:0] data_out,

output reg mosi,
output reg sclk,
output reg [7:0] data_in,
output reg busy
);

 由于需要用到spi时钟,spi时钟是一个慢速时钟,这里我所使用的是50Mhz的时钟,进行4分频得到一个12.5Mhz的spi时钟。所以需要一个俩位的计数器,当计数到1时归零,在定义一个标志位move,当计数器清零时move为高电平。但片选使能时,并且状态机处于等待使能,为了保持在传输时数据的稳定,需要把输出的数寄存到一个新的寄存器中data_out_s。在状态机处于接受完成的状态时把接受到的数据有data_in_s寄存器传出。由于spi的接收和发送的数据不在同一个时钟边沿采集,所以在接收到数据后在d为高电平时跟新数据。状态标志位当片选或状态机不处于等待使能信号时为高电平,代表发送未完成,处于忙碌的状态。

reg [1:0] d; always@(posedge clk) if(rst) d <= 0; else d <= d[1] ? 0 : d + 1;
wire move = d == 0;

reg [7:0] data_in_s; always@(posedge clk) if(st == 116) data_in <= data_in_s;
reg [7:0] data_out_s; always@(posedge clk) if(st == 10 & rw) data_out_s <= data_out;
reg miso_s; always@(posedge clk) if(d == 1)miso_s <= miso;

always@(posedge) busy <= rw || st != 10;

 最后就是状态机了,0状态为输出状态,时钟和要发送的数据都为0,10状态为使能信号等待状态,当收到使能时,等待一段时间,这个时间为使能后与发送第一个数据的间隔时间,具体时间可以在数据手册中查询,我这里等待了半个多的sclk时间,然后就可以接受与发送数据了,注意在flash的接受和发送也需要数据稳定的时间,具体也可以在数据手册中找到,flash的发送数据为上升沿采样,提前在下降沿时改变数据,接受时为下降沿采样,在sclk的上升时改变数据。

reg [7:0] st;
always@(posedge clk) if(rst) st <= 0;else case(st)
0:begin sclk <= 0;mosi <= 0;st <= 10; end
10: begin sclk <= 0; mosi <= 0; if(rw) st <= 20;

20: if(move) st <= 21;
21: if(move) st <= 100;

100: begin sclk <= 0; mosi <= data_out_s[7]; if(move) st <= st + 1;end
101: begin sclk <= 1; mosi <= data_out_s[7]; data_in_s[7] <= miso_s; if(move) st <= st + 1;end

102: begin sclk <= 0; mosi <= data_out_s[6]; if(move) st <= st + 1;end
103: begin sclk <= 0; mosi <= data_out_s[7]; data_in_s[6] <= miso_s; if(move) st <= st + 1;end

104: begin sclk <= 0; mosi <= data_out_s[5]; if(move) st <= st + 1;end
105: begin sclk <= 0; mosi <= data_out_s[5]; data_in_s[5] <= miso_s; if(move) st <= st + 1;end

106: begin sclk <= 0; mosi <= data_out_s[4]; if(move) st <= st + 1;end
107: begin sclk <= 0; mosi <= data_out_s[4]; data_in_s[4] <= miso_s; if(move) st <= st + 1;end

108: begin sclk <= 0; mosi <= data_out_s[3]; if(move) st <= st + 1;end
109: begin sclk <= 0; mosi <= data_out_s[3]; data_in_s[3] <= miso_s; if(move) st <= st + 1;end

110: begin sclk <= 0; mosi <= data_out_s[2]; if(move) st <= st + 1;end
111: begin sclk <= 0; mosi <= data_out_s[2]; data_in_s[2] <= miso_s; if(move) st <= st + 1;end

112: begin sclk <= 0; mosi <= data_out_s[1]; if(move) st <= st + 1;end
113: begin sclk <= 0; mosi <= data_out_s[1]; data_in_s[1] <= miso_s; if(move) st <= st + 1;end

114: begin sclk <= 0; mosi <= data_out_s[0]; if(move) st <= st + 1;end
115: begin sclk <= 0; mosi <= data_out_s[0]; data_in_s[0] <= miso_s; if(move) st <= st + 1;end

116: begin sclk <= 0;if(move) st <= st + 1;
117: if(move) st <= 10;
default: st <= 0;
endcase





endmodule

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值