1)CPOL:clock polarity,时钟极性。通信整个过程分为空闲时刻和通信时刻,SCK在数据发送前后的空闲状态是高电平,那么CPOL为1,否则为0。
模式0:CPOL = 0, CPHA = 0.
模式2: CPOL = 1, CPHA = 0.
模式3: CPOL = 1, CPHA=1.
总结:CPHA=1表示数据输出在第一个时钟周期的第一个沿,数据采样在第二个沿;
CPHA=0表示数据采样在第一个沿,数据输出在第二个沿.
CPOL=1表示第一个沿为下降沿;
CPOL=0表示第一个沿为上升沿.
根据从设备的技术手册可以确定SPI.
下面给出一个SPI控制器模块的实例代码:
(工作在模式0,100MHz分频产生1MHz的SCK时钟)
//代码参考自《搭建你的数字积木--数字电路与逻辑设计》,根据个人编码风格稍有改动
module spi_master
(
input mosi,
input clk,
input rst,
input busy,
input spi_send,
input [7:0] spi_data_out,
output reg sck,
output reg miso,
output reg cs,
output reg spi_send_done
);
reg [3:0] count;
parameter IDLE = 0;
parameter CS_L = 1;
parameter DATA = 2;
parameter FINISH = 3;
reg [4:0] cur_st;
reg [4:0] nxt_st;
reg [7:0] reg_data;
reg sck_reg;
reg [8:0] delay_count;
always @(posedge clk or negedge rst) begin
if(~rst)
delay_count <= 0;
else if(delay_count == 49)
delay_count <= 0;
else
delay_count <= delay_count + 1;
end
//产生1MHz的时钟
always @(posedge clk or negedge rst) begin
if(~rst)
sck_reg <= 0;
else if(delay_count == 49)
sck_reg <= ~sck_reg;
end
always @(*) begin
if(cs)
sck = 1;
else if(cur_st == FINISH)
sck = 1;
else if(!cs)
sck = sck_reg;
else
sck = 1;
end
always @(posedge sck_reg or negedge rst) begin
if(~rst)
cur_st <= IDLE;
else
cur_st <= nxt_st;
end
always @(*) begin
nxt_st <= cur_st;
case(cur_st)
IDLE:if(spi_send) nxt_st = CS_L;
CS_L:nxt_st = DATA;
DATA:if(count == 7) nxt_st = FINISH;
FINISH:if(busy) nxt_st = IDLE;
default:nxt_st = IDLE;
endcase
end
always @(*) begin
if(~rst)
spi_send_done = 0;
else if(cur_st == FINISH)
spi_send_done = 1;
else
spi_send_done = 0;
end
always @(posedge sck_reg or negedge rst) begin
if(~rst)
cs <= 1;
else if(cur_st == CS_L)
cs <= 0;
else if(cur_st == DATA)
cs <= 0;
else
cs <= 1;
end
always @(posedge sck_reg or negedge rst) begin
if(~rst)
count <= 0;
else if(cur_st == DATA)
count <= count + 1;
else if(cur_st == IDLE | cur_st == FINISH)
count <= 0;
end
always @(negedge sck_reg or negedge rst) begin
if(~rst)
miso <= 0;
else if(cur_st == DATA)begin
reg_data[7:1] <= reg_data[6:0];
miso <= reg_data[7];
end
else if(spi_send)
reg_data <= spi_data_out;
end
endmodule
没有回复内容