板级通信总线之SPI及其Verilog实现

更新时间:2023-06-23 10:31:37 阅读: 评论:0

板级通信总线之SPI及其Verilog实现
打算写⼏篇专题,系统总结下常⽤的⽚上总线、现场总线,就先从最常⽤的SPI开始吧。
1. SPI是⼲什么的?除了SPI还有那些其它电路板及的通讯总线?有何差别?
相信接触过MCU的同学对SPI都不陌⽣,详细定义就不罗嗦了。SPI常⽤的场合包括ADC读写、存储芯⽚读写、MCU间通讯等等。可以⼀主多从(通过⽚选来选择Slave),也可以做成菊花链等等形式的拓扑。与SPI类似的总线还有IIC、UART等,甚⾄还有很多单根线的总线,原理都是基于简单的串⾏通信,区别在于收发时序和连接拓扑。要熟练使⽤这些总线,关键在于理解其时序图,在此基础上创造各种变种的总线形式也不是难事(当然为了设计的通⽤性不建议这么做)。
以下维基百科的SPI词条介绍⾮常全⾯,推荐阅读。
2. SPI是什么样的?
在此借⽤⼀张维基百科上的图,SPI通常有4根线,SS⽤于选定当前通信的slave,SCLK为通信的基准时钟,采样/发送都在时钟边沿执⾏,MOSI、MISO为串⾏的数据线。
以下是⼀个典型的SPI时序图,Master和Slave均在时钟上升沿采样,下降沿发送数据。数据从最⾼位(MSB)开始发送。
需要注意图中所有的时序关系都要被满⾜,包括CS下降沿到第1个时钟上升沿间隔(t sclk_su)、数据的建⽴时间(t SU)、保持时间(t HD)等等。通常这些参数由具体的器件决定,如果不满⾜则有通信失败的风险。
3. 如何使⽤SPI?SPI有哪⼏种配置模式(相位、极性)?
根据SPI时钟信号的空闲状态、是上升沿采样还是下降沿采样,SPI有四种模式。CPOL=0表⽰时钟空闲时为低电平,反之为⾼电平;CPHA=0表⽰时钟信号第⼀个边沿是采样边沿,反之表⽰第2个边沿是采样边沿。对于带SPI接⼝的MCU⽽⾔,通常可由软件配置
CPOL(Clock Polarity)、CPHA(Clock Pha),以适应和不同类型器件的通信。
4. 如何⽤verilog 编写SPI协议?
以下是使⽤verilog写的SPI主从通信代码,经过实测通信OK,可供参考。主从都在下降沿置数,同时在下降沿采样上⼀次发送的数据。为了尽量在主时钟较慢的情况下提⾼通信速度,采⽤的是⾮同步采样⽅式(即直接⽤SCLK边沿触发采样/发送,⽽不⽤主时钟对SCLK进⾏同步)。
module Serial2Parallel_Master #(
parameter SCLK_DIVIDER = 8'd0 //Sclk Freq = Clk/2 / (SCLK_DIVIDER + 1)
)(
input rst_n,
input clk,
input sDataRd,
input [15:0] pDataWr,
output dataCS,
output dataSclk,
output sDataWr,
output [15:0] pDataRd
);
// counter,ud to generate dataSclk signal
reg dataCS_reg;
reg dataSclk_reg;
reg[7:0] Count1;
always @(podge clk or negedge rst_n)
if(!rst_n)
Count1 <= 8'd0;
el if(Count1 == SCLK_DIVIDER)
Count1 <= 8'd0;
el
Count1 <= Count1 + 1'b1;
// generate CS and Sclk quence
reg [5:0] i;//Step number
always @(podge clk or negedge rst_n)
if(!rst_n)begin
i <= 6'd0;
dataSclk_reg <= 1'b1;//Sclk high at ret
dataCS_reg <= 1'b1;    //CS high at ret
end
el begin
ca(i)
//pull down CS at the beginning
6'd0:
if(Count1 == SCLK_DIVIDER) begin
i <= i + 1'b1;
dataSclk_reg <= 1'b1;
dataCS_reg <= 1'b0;
end
el;
//generate 1st to 17th Sclk falling edge
6'd1,6'd3,6'd5,6'd7,6'd9,6'd11,6'd13,6'd15,6'd17,6'd19,6'd21,6'd23,6'd25,5'd27,6'd29,6'd31,6'd33:
if(Count1 == SCLK_DIVIDER) begin
dataSclk_reg <= 1'b0;
dataCS_reg <= 1'b0;
红翡i <= i + 1'b1;
end
el;
//generate 1st to 16th Sclk rising edge
6'd2,6'd4,6'd6,6'd8,6'd10,6'd12,6'd14,6'd16,6'd18,6'd20,6'd22,6'd24,6'd26,6'd28,6'd30,6'd32:
if(Count1 == SCLK_DIVIDER) begin
dataSclk_reg <= 1'b1;
dataCS_reg <= 1'b0;
i <= i + 1'b1;
i <= i + 1'b1;
end
el;
6'd34://CS and Sclk go high
if(Count1 == SCLK_DIVIDER) begin
dataSclk_reg <= 1'b1;
dataCS_reg <= 1'b1;
i <= i + 1'b1;
end
el;
6'd35://CS keep high, Sclk go low
if(Count1 == SCLK_DIVIDER) begin
酌怎么读dataSclk_reg <= 1'b0;
dataCS_reg <= 1'b1;
i <= 6'd0;
end
el ;
default ;
endca
end ;
// - receive and nd SPI data
reg sDataWr_reg;
reg [15:0] pDataRd_reg;
reg rxDone_reg;
reg [5:0] j;
always @(negedge dataSclk or negedge rst_n)
if(!rst_n) begin
j <= 6'd0;
sDataWr_reg <= 1'b0;
pDataRd_reg <= 16'd0;
rxDone_reg <= 1'b0;
end
// - CS high,clear j & AD data
el if(dataCS) begin
j <= 6'd0;
sDataWr_reg <= 1'b0;
pDataRd_reg <= 16'd0;
看图猜字谜
rxDone_reg <= 1'b0;
end
el begin
// - first falling of Sclk, nd MSB of nd data
if(j == 6'd0) begin
j <= j + 1'b1;
sDataWr_reg <= pDataWr[15];//nd data
pDataRd_reg <= 16'd0;//receive data clear
rxDone_reg <= 1'b0;
end
// - 2nd to 16th falling of Sclk
el if(j <= 6'd15) begin
j <= j + 1'b1;
sDataWr_reg <= pDataWr[15-j];//nd data
pDataRd_reg[16-j] <= sDataRd;//receive data
rxDone_reg <= 1'b0;
end
// - at 17th falling of sclk_fbk, CS is still low, receive LSB of receive data el if(j == 6'd16) begin
j <= j + 1'b1;
sDataWr_reg <= 1'b0;//nd data clear
pDataRd_reg[0] <= sDataRd;//receive data
美食的图片rxDone_reg <= 1'b1;//receive done
end
el begin
el begin
j <= j;
sDataWr_reg <= sDataWr_reg;                pDataRd_reg <= pDataRd_reg;                rxDone_reg <= rxDone_reg;
end
end
// - data latch for pDataRd
reg [15:0] pDataRd_l;
always @(podge clk or negedge rst_n)
if(!rst_n)
pDataRd_l <= 16'd0;
el if(rxDone_reg) begin
pDataRd_l <= pDataRd_reg;
闪电一瞥end
el begin
pDataRd_l <= pDataRd_l;
end
// - delay sDataWr for 1 main clk(10ns)
reg sDataWr_dly;
always @(podge clk or negedge rst_n)
if(!rst_n)
sDataWr_dly <= 1'b0;
el if(sDataWr_reg) begin
sDataWr_dly <= 1'b1;
end
el begin
sDataWr_dly <= 1'b0;
end
// - output assignment
assign dataCS = dataCS_reg;
assign dataSclk = dataSclk_reg;
植树手抄报
assign sDataWr = sDataWr_dly;
assign pDataRd = pDataRd_l; endmodule
View Code:SPI Master
1module Serial2Parallel_Slave (
2
3input rst_n,
4input clk,
5
如何预防疾病
6input dataCS,
7input dataSclk,
8
9input sDataRd,
10input [15:0] pDataWr,
11
12output sDataWr,
13output [15:0] pDataRd
14 );
15
16// - SPI read and write
17reg sDataWr_reg;
18reg [15:0] pDataRd_reg;
19reg rxDone_reg;
20reg [5:0] j;//operation steps
20reg [5:0] j;//operation steps
21always @(negedge dataSclk or negedge rst_n)
22if(!rst_n) begin
23            j <= 6'd0;
24            sDataWr_reg <= 1'b0;
25            pDataRd_reg <= 16'd0;
26            rxDone_reg <= 1'b0;
27end
28// - CS high,clear j & AD data
29el if(dataCS) begin
30            j <= 6'd0;
31            sDataWr_reg <= 1'b0;
32            pDataRd_reg <= 16'd0;
33            rxDone_reg <= 1'b0;
34end
35el begin
36// - first falling of Sclk, nd MSB of nd data
37if(j == 6'd0) begin
38                j <= j + 1'b1;
39                sDataWr_reg <= pDataWr[15];//nd data
40                pDataRd_reg <= 16'd0;//receive data clear
41                rxDone_reg <= 1'b0;
42end
43
44// - 2nd to 16th falling of Sclk
45el if(j <= 6'd15) begin
46                j <= j + 1'b1;
47                sDataWr_reg <= pDataWr[15-j];//nd data
48                pDataRd_reg[16-j] <= sDataRd;//receive data
49                rxDone_reg <= 1'b0;
50end
51
52// - at 17th falling of sclk_fbk, CS is still low, receive LSB of receive data 53el if(j == 6'd16) begin
54                j <= j + 1'b1;
55                sDataWr_reg <= 1'b0;//nd data clear
56                pDataRd_reg[0] <= sDataRd;//receive data
57                rxDone_reg <= 1'b1;//receive done
58end
59el begin
60                j <= j;
61                sDataWr_reg <= sDataWr_reg;
62                pDataRd_reg <= pDataRd_reg;
63                rxDone_reg <= rxDone_reg;
64end
65end
66
67// - data latch for pDataRd
68reg [15:0] pDataRd_l;
69always @(podge dataCS or negedge rst_n)
70if(!rst_n)
71            pDataRd_l <= 16'd0;
72el if(rxDone_reg) begin
73            pDataRd_l <= pDataRd_reg;
74end
75el begin
76            pDataRd_l <= pDataRd_l;
77end
78
79// - output assignment
80assign sDataWr = sDataWr_reg;
多肉简笔画81assign pDataRd = pDataRd_l;
82
83
84endmodule

本文发布于:2023-06-23 10:31:37,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1051140.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:总线   时钟   采样   下降   时序   器件
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图