FPGA通讯协议学习实践1- SPI协议
1、前言
在具体的通信项目中,CPOL,CPHA可能就是固定不变的,发送/采集数据位宽也可能是固定不变的,那样的话,项目做起来就会很简单了(以前使用序列机实现的)。我自己实践的时候,是假设这些东西是可变的,所以就把这个事情就搞得很复杂了。当然,复杂的原因这只是其一,更多的可能是自己没太多经验与智慧吧。
作为新手,肯定是有很多不完善的地方,所以仅供参考,如果有误,可以加我Q1011090284,我会更改。
2、系统功能
a、可设置 CPOL(Clock Polarity)时钟极性——配置SCLK空闲态状态,CPOL(Clock Phase)时钟相位——配置数据采样在第1个/第2个边沿。
b、可设置通信频率;
c、可配置发送/采集数据位宽
3、模块划分
将SPI通讯模块划分成以下模块:
- 时钟模块
- 数据采集模块
- 数据发送模块
- 控制模块

4、模块细化
a.时钟模块:
功能:
1) 输出SPI_SCK时钟信号。预设了14种不同的时钟频率可供选择。默认1KHz
2) 读取CPOL(Clock Polarity)时钟极性——配置SCK空闲态状态。
3 ) 输出SCK_Posedge、SCK_Negedge信号,供采集/发送模块使用
4) 采集结束之后,延迟半个采集时钟周期(要少6个系统时钟周期),给上层发送SPI通信结束信号

代码如下
1 /***************************************************
2 * Module Name : SPI_Clk_Module
3 * Engineer : 王小虎
4 * Target Device : EP4CE10F17C8 50MHZ时钟频率
5 * Tool versions : Quartus II 13.0
6 * Create Date : 2019
7 * Revision : v1.0
8 * Description : 1、SPI通讯SCK时钟信号输出(可选频率)
9 2、SCK_Posedge、SCK_Negedge标志位输出
10 **************************************************/
11 module SPI_Clk_Module(
12 clk,
13 rst_n,
14 SPI_SCK_EN,
15 SPI_SCK_STOP,
16 SPI_SCK_Freq_Sel,
17 SPI_SCK_CPOL,
18 SCK_Posedge,
19 SCK_Negedge,
20 Delay_Done,
21 SPI_SCK
22 );
23 //=================================<端口>===========================
24 //-- 物理端口
25 input clk; //时钟信号
26 input rst_n; //复位信号
27 output reg SPI_SCK; //SPI时钟信号
28 //-- 上级系统通信
29 input SPI_SCK_EN; //SPI时钟使能信号
30 input SPI_SCK_STOP; //SPI时钟输出停止信号(重置)
31 input [3:0]SPI_SCK_Freq_Sel; //SPI频率选择信号
32 input SPI_SCK_CPOL; //SPI空闲状态控制信号 0 空闲低电平 1 空闲高电平
33 output reg SCK_Posedge; //SPI时钟信号SCK上升沿标记
34 output reg SCK_Negedge; //SPI时钟信号SCK下降沿标记
35 output reg Delay_Done; //停止时钟输出信号
36 //-- 下级系统通信
37
38 //-- 内部信号
39 reg [3:0]freq; //频率选择寄存器
40 reg SCK_Init_O; //时钟默认信号寄存器
41 reg [15:0]SCK_CNT_FULL; //分频计数值
42 reg [15:0]DIV_CNT; //分频计数寄存器
43 reg SPI_SCK_Ostate; //时钟输出状态
44 reg Done_delay_en; //停止延时使能
45 reg [15:0]Done_delay_cnt; //STOP信号延迟寄存器
46 //-------------------------------------------------------------------
47 //--序号01 功能描述:寄存上级指令或数据
48 //-------------------------------------------------------------------
49 always@(posedge clk or negedge rst_n)
50 if(!rst_n)
51 freq <= 4'd0;
52 else if(SPI_SCK_EN)
53 freq <= SPI_SCK_Freq_Sel;
54 else
55 freq <= freq;
56
57 always@(posedge clk or negedge rst_n)
58 if(!rst_n)
59 SCK_Init_O <= 1'b0;
60 else if(SPI_SCK_EN)
61 SCK_Init_O <= SPI_SCK_CPOL;
62 else if(SPI_SCK_Ostate)
63 SCK_Init_O <= SCK_Init_O;
64 else
65 SCK_Init_O <= SPI_SCK_CPOL; //便于控制SCK空闲状态,可实时改变
66
67
68 //-------------------------------------------------------------------
69 //--序号02 功能描述:分频信号 SCK 、标记信号SCK_Posedge、SCK_Negedge输出
70 //-------------------------------------------------------------------
71 //--SPI_SCK_Ostate时钟输出状态确定
72 always@(posedge clk or negedge rst_n)
73 if(!rst_n)
74 SPI_SCK_Ostate <= 1'b0;
75 else if(SPI_SCK_EN)
76 SPI_SCK_Ostate <= 1'b1;
77 else if(Delay_Done)
78 SPI_SCK_Ostate <= 1'b0;
79 else
80 SPI_SCK_Ostate <= SPI_SCK_Ostate;
81
82 //--分频计数器
83 always@(posedge clk or negedge rst_n)
84 if(!rst_n)
85 DIV_CNT <= 16'd0;
86 else if(SPI_SCK_Ostate)
87 begin
88 if(DIV_CNT == SCK_CNT_FULL)
89 DIV_CNT <= 16'd0;
90 else
91 DIV_CNT <= DIV_CNT + 1'b1;
92 end
93 else
94 DIV_CNT <= 16'd0;
95
96 //--SPI SCK时钟信号输出
97 always@(posedge clk or negedge rst_n)
98 if(!rst_n)
99 SPI_SCK <= 1'b0;
100 else if(SPI_SCK_Ostate)
101 begin
102 if(DIV_CNT == (SCK_CNT_FULL >> 1'b1))
103 SPI_SCK <= ~SPI_SCK;
104 else if(DIV_CNT == 1'b0)
105 SPI_SCK <= SCK_Init_O;
106 else
107 SPI_SCK <= SPI_SCK;
108 end
109 else
110 SPI_SCK <= SCK_Init_O;
111
112 //--标记信号SCK_Posedge输出
113 always@(posedge clk or negedge rst_n)
114 if(!rst_n)
115 SCK_Posedge <= 1'b0;
116 else if( !SCK_Init_O && DIV_CNT == (SCK_CNT_FULL >> 1'b1))
117 SCK_Posedge <= 1'b1;
118 else if( SCK_Init_O && DIV_CNT == SCK_CNT_FULL)
119 SCK_Posedge <= 1'b1;
120 else
121 SCK_Posedge <= 1'b0;
122
123 //--标记信号SCK_Negedge输出
124 always@(posedge clk or negedge rst_n)
125 if(!rst_n)
126 SCK_Negedge <= 1'b0;
127 else if( SCK_Init_O && DIV_CNT == (SCK_CNT_FULL >> 1'b1))
128 SCK_Negedge <= 1'b1;
129 else if( !SCK_Init_O && DIV_CNT == SCK_CNT_FULL)
130 SCK_Negedge <= 1'b1;
131 else
132 SCK_Negedge <= 1'b0;
133 //-------------------------------------------------------------------
134 //--序号03 功能描述:SCK时钟延迟停止函数
135 //-------------------------------------------------------------------
136 //--Done_delay_en
137 always@(posedge clk or negedge rst_n)
138 if(!rst_n)
139 Done_delay_en <= 1'b0;
140 else if(SPI_SCK_STOP)
141 Done_delay_en <= 1'b1;
142 else if(Delay_Done)
143 Done_delay_en <= 1'b0;
144 else
145 Done_delay_en <= Done_delay_en;
146 //--Done_delay_cnt
147 always@(posedge clk or negedge rst_n)
148 if(!rst_n)
149 Done_delay_cnt <= 16'd0;
150 else if(Done_delay_en)
151 Done_delay_cnt <= Done_delay_cnt + 1'b1;
152 else
153 Done_delay_cnt <= 16'd0;
154 //--Done
155 always@(posedge clk or negedge rst_n)
156 if(!rst_n)
157 Delay_Done <= 1'b0;
158 else if(Done_delay_cnt == (SCK_CNT_FULL >> 1) - 3'd6)
159 Delay_Done <= 1'b1;
160 else
161 Delay_Done <= 1'b0;
162 //-------------------------------------------------------------------
163 //--序号04 功能描述:SCK时钟频率查找表
164 //-------------------------------------------------------------------
165 always@(*)
166 begin
167 case(freq)
168 4'd0 :SCK_CNT_FULL = 16'd49999 ; // 1 KHz
169 4'd1 :SCK_CNT_FULL = 16'd24999 ; // 2 KHz
170 4'd2 :SCK_CNT_FULL = 16'd12499 ; // 4 KHz
171 4'd3 :SCK_CNT_FULL = 16'd6249 ; // 8 KHz
172 4'd4 :SCK_CNT_FULL = 16'd4999 ; // 10 KHz
173 4'd5 :SCK_CNT_FULL = 16'd2499 ; // 20 KHz
174 4'd6 :SCK_CNT_FULL = 16'd1249 ; // 40 KHz
175 4'd7 :SCK_CNT_FULL = 16'd624 ; // 80 KHz
176 4'd8 :SCK_CNT_FULL = 16'd499 ; // 100 KHz
177 4'd9 :SCK_CNT_FULL = 16'd249 ; // 200 KHz
178 4'd10:SCK_CNT_FULL = 16'd124 ; // 400 KHz
179 4'd11:SCK_CNT_FULL = 16'd99 ; // 500 KHz
180 4'd12:SCK_CNT_FULL = 16'd49 ; // 1 MHz
181 4'd13:SCK_CNT_FULL = 16'd24 ; // 2 MHz
182 default:SCK_CNT_FULL = 16'd49999 ; // 1 KHz
183 endcase
184 end
185
186 endmodule
b.数据采集模块:
功能:
1) 采集8/16位数据

代码如下
1 /***************************************************
2 * Module Name : SPI_Rx_Module
3 * Engineer : 王小虎
4 * Target Device : EP4CE10F17C8
5 * Tool versions : Quartus II 13.0
6 * Create Date : 2019
7 * Revision : v1.0
8 * Description : 1、SPI通信数据采集模块;采集顺序MSB --> LSB
9 2、可通过设置SPI_SCK_CPOL、SPI_SCK_CPHA满足四种不同传输模式
10 3、数据位宽可设置 8/16位
11 **************************************************/
12 module SPI_Rx_Module(
13 clk,
14 rst_n,
15 SPI_Rx_EN,
16 SPI_Rx_Data_Width,
17 SPI_SCK_CPOL,
18 SPI_SCK_CPHA,
19 SCK_Posedge,
20 SCK_Negedge,
21 SPI_Rx_Data,
22 SPI_Rx_Done,
23 SPI_MISO
24 );
25 //=================================<端口>===========================
26 //-- 物理端口
27 input clk; //时钟信号
28 input rst_n; //复位信号
29 input SPI_MISO; //SPI输入信号
30 //-- 上级系统通信
31 input SPI_Rx_EN; //接收使能信号
32 input [4:0]SPI_Rx_Data_Width; //将接收数据位宽
33 input SPI_SCK_CPOL; //时钟极性设置
34 input SPI_SCK_CPHA; //时钟相位设置
35 input SCK_Posedge; //时钟上升沿标记
36 input SCK_Negedge; //时钟下降沿标记
37 output reg [15:0]SPI_Rx_Data; //输出采集数据
38 output reg SPI_Rx_Done; //采集结束标志
39 //-- 下级系统通信
40
41 //-- 内部信号
42 reg Rx_state; //采集状态
43 reg [4:0]data_Width; //采集数据位宽寄存器
44 reg CPOL; //时钟极性参数寄存器
45 reg CPHA; //时钟相位设置寄存器
46 reg [4:0]Rx_cnt; //采集数据计数器
47 reg [15:0]data; //采集数据寄存器
48
49 //-------------------------------------------------------------------
50 //--序号01 功能描述:寄存上级指令或数据
51 //-------------------------------------------------------------------
52 //--采集数据位宽寄存器
53 always@(posedge clk or negedge rst_n)
54 if(!rst_n)
55 data_Width <= 5'd0;
56 else if(SPI_Rx_EN)
57 data_Width <= SPI_Rx_Data_Width;
58 else
59 data_Width <= data_Width;
60 //--时钟极性参数寄存器
61 always@(posedge clk or negedge rst_n)
62 if(!rst_n)
63 CPOL <= 1'b0;
64 else if(SPI_Rx_EN)
65 CPOL <= SPI_SCK_CPOL;
66 else
67 CPOL <= CPOL;
68 //--时钟相位设置寄存器
69 always@(posedge clk or negedge rst_n)
70 if(!rst_n)
71 CPHA <= 1'b0;
72 else if(SPI_Rx_EN)
73 CPHA <= SPI_SCK_CPHA;
74 else
75 CPHA <= CPHA;
76 //-------------------------------------------------------------------
77 //--序号02 功能描述:数据采集
78 //-------------------------------------------------------------------
79 //--采集状态
80 always@(posedge clk or negedge rst_n)
81 if(!rst_n)
82 Rx_state <= 1'b0;
83 else if(SPI_Rx_EN)
84 Rx_state <= 1'b1;
85 else if(SPI_Rx_Done)
86 Rx_state <= 1'b0;
87 else
88 Rx_state <= Rx_state;
89
90 //--采集结束标志
91 always@(posedge clk or negedge rst_n)
92 if(!rst_n)
93 SPI_Rx_Done <= 1'b0;
94 else if( Rx_cnt == data_Width && Rx_state)
95 SPI_Rx_Done <= 1'b1;
96 else
97 SPI_Rx_Done <= 1'b0;
98
99 //--采集数据计数器
100 always@(posedge clk or negedge rst_n)
101 if(!rst_n)
102 Rx_cnt <= 5'd0;
103 else if(Rx_state)
104 begin
105 if(Rx_cnt >= data_Width)
106 Rx_cnt <= 5'd0;
107 else if(CPHA)
108 begin
109 if((!CPOL && SCK_Negedge) || ((CPOL && SCK_Posedge)))
110 Rx_cnt <= Rx_cnt + 1'b1;
111 else
112 Rx_cnt <= Rx_cnt;
113 end
114 else
115 begin
116 if((!CPOL && SCK_Posedge) || (CPOL && SCK_Negedge))
117 Rx_cnt <= Rx_cnt + 1'b1;
118 else
119 Rx_cnt <= Rx_cnt;
120 end
121 end
122 else
123 Rx_cnt <= 5'd0;
124
125 //--采集数据
126 always@(posedge clk or negedge rst_n)
127 if(!rst_n)
128 data <= 16'd0;
129 else if(Rx_state)
130 begin
131 if(CPHA)
132 begin
133 if((!CPOL && SCK_Negedge) || ((CPOL && SCK_Posedge)))
134 data <= {data[14:0],SPI_MISO};
135 else
136 data <= data;
137 end
138 else
139 begin
140 if((!CPOL && SCK_Posedge) || (CPOL && SCK_Negedge))
141 data <= {data[14:0],SPI_MISO};
142 else
143 data <= data;
144 end
145 end
146 else
147 data <= 16'd0;
148
149 //--采集数据
150 always@(posedge clk or negedge rst_n)
151 if(!rst_n)
152 SPI_Rx_Data <= 16'd0;
153 else if(Rx_cnt == data_Width)
154 SPI_Rx_Data <= data;
155 else
156 SPI_Rx_Data <= SPI_Rx_Data;
157
158 endmodule
c.数据发送模块:
功能:
1) 发送8/16位数据

代码如下
1 /***************************************************
2 * Module Name : SPI_Tx_Module
3 * Engineer : 王小虎
4 * Target Device : EP4CE10F17C8
5 * Tool versions : Quartus II 13.0
6 * Create Date : 2019
7 * Revision : v1.0
8 * Description : 1、可发送8/16位宽数据;
9 2、发送计数值以采集值作参考
10 **************************************************/
11 module SPI_Tx_Module(
12 clk,
13 rst_n,
14 SPI_Tx_EN,
15 SPI_Tx_Data_Width,
16 SPI_Tx_Data,
17 SPI_SCK_CPOL,
18 SPI_SCK_CPHA,
19 SCK_Posedge,
20 SCK_Negedge,
21 SPI_Tx_Done,
22 SPI_MOSI
23 );
24 //=================================<端口>===========================
25 //-- 物理端口
26 input clk; //时钟信号
27 input rst_n; //复位信号
28 output reg SPI_MOSI; //MOSI输出信号
29 //-- 上级系统通信
30 input SPI_Tx_EN; //发送使能信号
31 input [4:0]SPI_Tx_Data_Width; //发送数据位宽
32 input [15:0]SPI_Tx_Data; //待发送数据
33 input SPI_SCK_CPOL; //时钟极性
34 input SPI_SCK_CPHA; //时钟相位
35 input SCK_Posedge; //上升沿标记
36 input SCK_Negedge; //下降沿标记
37 output reg SPI_Tx_Done; //发送结束标记
38 //-- 下级系统通信
39
40 //-- 内部信号
41 reg Tx_state; //发送状态
42 reg [4:0]data_width; //数据位宽寄存器
43 reg [15:0]data; //待发送数据寄存器
44 reg CPOL; //时钟极性寄存器
45 reg CPHA; //时钟相位寄存器
46 reg [4:0]Tx_cnt; //发送数据计数寄存器
47 //-------------------------------------------------------------------
48 //--序号01 功能描述:寄存上级指令或数据
49 //-------------------------------------------------------------------
50 //--数据位宽寄存器
51 always@(posedge clk or negedge rst_n)
52 if(!rst_n)
53 data_width <= 5'd0;
54 else if(SPI_Tx_EN)
55 data_width <= SPI_Tx_Data_Width;
56 else
57 data_width <= data_width;
58
59 //--data寄存器
60 always@(posedge clk or negedge rst_n)
61 if(!rst_n)
62 data <= 16'd0;
63 else if(SPI_Tx_EN) //如果待发送数据不是16位
64 data <= ( SPI_Tx_Data << ( 5'd16 - SPI_Tx_Data_Width) );
65 else if(Tx_state)begin
66 if(CPHA)begin
67 if( Tx_cnt >1'b0 )
68 if( (!CPOL && SCK_Posedge) || (CPOL && SCK_Negedge) )
69 data <= {data[14:0],data[15]};
70 else
71 data <= data;
72 else
73 data <= data;
74 end
75 else if( (CPOL && SCK_Posedge) || (!CPOL && SCK_Negedge))
76 data <= {data[14:0],data[15]};
77 else
78 data <= data;
79 end
80 else
81 data <= data;
82
83 //--时钟极性参数寄存器
84 always@(posedge clk or negedge rst_n)
85 if(!rst_n)
86 CPOL <= 1'b0;
87 else if(SPI_Tx_EN)
88 CPOL <= SPI_SCK_CPOL;
89 else
90 CPOL <= CPOL;
91
92 //--时钟相位设置寄存器
93 always@(posedge clk or negedge rst_n)
94 if(!rst_n)
95 CPHA <= 1'b0;
96 else if(SPI_Tx_EN)
97 CPHA <= SPI_SCK_CPHA;
98 else
99 CPHA <= CPHA;
100 //-------------------------------------------------------------------
101 //--序号02 功能描述:发送数据模块
102 //-------------------------------------------------------------------
103 //--发送状态寄存器
104 always@(posedge clk or negedge rst_n)
105 if(!rst_n)
106 Tx_state <= 1'b0;
107 else if(SPI_Tx_EN)
108 Tx_state <= 1'b1;
109 else if(SPI_Tx_Done)
110 Tx_state <= 1'b0;
111 else
112 Tx_state <= Tx_state;
113 //--发送数据计数器
114 always@(posedge clk or negedge rst_n)
115 if(!rst_n)
116 Tx_cnt <= 5'd0;
117 else if(Tx_state)
118 begin
119 if(Tx_cnt >= data_width)
120 Tx_cnt <= 5'd0;
121 else if(CPHA)
122 begin
123 if((!CPOL && SCK_Negedge) || ((CPOL && SCK_Posedge)))
124 Tx_cnt <= Tx_cnt + 1'b1;
125 else
126 Tx_cnt <= Tx_cnt;
127 end
128 else
129 begin
130 if((!CPOL && SCK_Posedge) || (CPOL && SCK_Negedge))
131 Tx_cnt <= Tx_cnt + 1'b1;
132 else
133 Tx_cnt <= Tx_cnt;
134 end
135 end
136 else
137 Tx_cnt <= 5'd0;
138 //--发送数据
139 always@(posedge clk or negedge rst_n)
140 if(!rst_n)
141 SPI_MOSI <= 1'b0;
142 else if(Tx_state)
143 SPI_MOSI <= data[15];
144 else
145 SPI_MOSI <= 1'd1; //在仅采集的情况下,让SPI_MOSI端口置1
146
147
148 //--SPI_Tx_Done
149 always@(posedge clk or negedge rst_n)
150 if(!rst_n)
151 SPI_Tx_Done <= 1'b0;
152 else if( Tx_cnt == data_width && Tx_state)
153 SPI_Tx_Done <= 1'b1;
154 else
155 SPI_Tx_Done <= 1'b0;
156 endmodule
d.控制模块:
功能:
1) 输出片选信号
代码如下
1 /***************************************************
2 * Module Name : SPI_CTL
3 * Engineer : 王小虎
4 * Target Device : EP4CE10F17C8
5 * Tool versions : Quartus II 13.0
6 * Create Date : 2019
7 * Revision : v1.0
8 * Description : 1、片选信号默认为1,选中为0;
9 2、时钟结束信号以采集结束信号为标志
10 3、SPI_Done信号在采集结束SPI_Rx_Done之后延迟半个采集周期之后发送
11 **************************************************/
12 module SPI_CTL(
13 clk,
14 rst_n,
15 SPI_EN,
16 SPI_Done,
17 SPI_SCK_CPOL,
18 SPI_SCK_CPHA,
19 SPI_SCK_Freq_Sel,
20 SPI_Rx_Data_Width,
21 SPI_Rx_Data,
22 SPI_Tx_Data_Width,
23 SPI_Tx_Data,
24 SPI_CS,
25 SPI_MOSI,
26 SPI_MISO,
27 SPI_SCK
28 );
29 //=================================<端口>===========================
30 //-- 物理端口
31 input clk; //时钟信号
32 input rst_n; //复位信号
33 output reg SPI_CS; //片选信号
34 input SPI_MISO; //SPI输入信号
35 output SPI_MOSI; //MOSI输出信号
36 output SPI_SCK; //SPI时钟输出信号
37 //-- 上级系统通信
38 input SPI_EN; //SPI通信使能信号
39 output SPI_Done; //采集结束标志
40 input SPI_SCK_CPOL; //时钟极性设置
41 input SPI_SCK_CPHA; //时钟相位设置
42 input [3:0]SPI_SCK_Freq_Sel; //时钟频率选择信号
43 input [4:0]SPI_Rx_Data_Width; //将接收数据位宽
44 output[15:0]SPI_Rx_Data; //输出采集数据
45 input [4:0]SPI_Tx_Data_Width; //发送数据位宽
46 input [15:0]SPI_Tx_Data; //待发送数据
47
48 //-- 下级系统通信
49 wire SCK_Posedge; //时钟上升沿标记
50 wire SCK_Negedge; //时钟下降沿标记
51 wire SPI_Rx_Done; //采集结束标志
52 wire SPI_Tx_Done; //发送结束标记
53 wire Delay_Done; //延时停止信号
54 //-- 内部信号
55 //-------------------------------------------------------------------
56 //--序号01 功能描述:SPI_Done
57 //-------------------------------------------------------------------
58 assign SPI_Done = Delay_Done;
59 //-------------------------------------------------------------------
60 //--序号02 功能描述:SPI_CS
61 //-------------------------------------------------------------------
62 always@(posedge clk or negedge rst_n)
63 if(!rst_n)
64 SPI_CS <= 1'b1;
65 else if(SPI_EN)
66 SPI_CS <= 1'b0;
67 else if(Delay_Done)
68 SPI_CS <= 1'b1;
69 else
70 SPI_CS <= SPI_CS;
71 //-------------------------------------------------------------------
72 //-- 模块例化
73 //-------------------------------------------------------------------
74 SPI_Clk_Module Clk_Module(
75 .clk(clk),
76 .rst_n(rst_n),
77 .SPI_SCK_EN(SPI_EN),
78 .SPI_SCK_STOP(SPI_Rx_Done),
79 .SPI_SCK_Freq_Sel(SPI_SCK_Freq_Sel),
80 .SPI_SCK_CPOL(SPI_SCK_CPOL),
81 .SCK_Posedge(SCK_Posedge),
82 .SCK_Negedge(SCK_Negedge),
83 .Delay_Done(Delay_Done),
84 .SPI_SCK(SPI_SCK)
85 );
86
87 SPI_Rx_Module Rx_Module(
88 .clk(clk),
89 .rst_n(rst_n),
90 .SPI_Rx_EN(SPI_EN),
91 .SPI_Rx_Data_Width(SPI_Rx_Data_Width),
92 .SPI_SCK_CPOL(SPI_SCK_CPOL),
93 .SPI_SCK_CPHA(SPI_SCK_CPHA),
94 .SCK_Posedge(SCK_Posedge),
95 .SCK_Negedge(SCK_Negedge),
96 .SPI_Rx_Data(SPI_Rx_Data),
97 .SPI_Rx_Done(SPI_Rx_Done),
98 .SPI_MISO(SPI_MISO)
99 );
100 SPI_Tx_Module Tx_Module(
101 .clk(clk),
102 .rst_n(rst_n),
103 .SPI_Tx_EN(SPI_EN),
104 .SPI_Tx_Data_Width(SPI_Tx_Data_Width),
105 .SPI_Tx_Data(SPI_Tx_Data),
106 .SPI_SCK_CPOL(SPI_SCK_CPOL),
107 .SPI_SCK_CPHA(SPI_SCK_CPHA),
108 .SCK_Posedge(SCK_Posedge),
109 .SCK_Negedge(SCK_Negedge),
110 .SPI_Tx_Done(SPI_Tx_Done),
111 .SPI_MOSI(SPI_MOSI)
112 );
113
114 endmodule
e.顶层模块:
代码如下
1 /***************************************************
2 * Module Name : SPI_TOP
3 * Engineer : 王小虎
4 * Target Device : EP4CE10F17C8
5 * Tool versions : Quartus II 13.0
6 * Create Date : 2019
7 * Revision : v1.0
8 * Description : 1、SPI_SCK_CPOL/SPI_SCK_CPOL可设置
9 2、采集/发送数据位宽可设置(是否鸡肋?)
10 3、发送频率可选择。采用查找表形式,可更改
11 **************************************************/
12 module SPI_TOP(
13 clk,
14 rst_n,
15 SPI_EN,
16 SPI_Done,
17 SPI_SCK_CPOL,
18 SPI_SCK_CPHA,
19 SPI_SCK_Freq_Sel,
20 SPI_Rx_Data_Width,
21 SPI_Rx_Data,
22 SPI_Tx_Data_Width,
23 SPI_Tx_Data,
24 SPI_CS,
25 SPI_MOSI,
26 SPI_MISO,
27 SPI_SCK
28 );
29 //=================================<端口>===========================
30 //-- 物理端口
31 input clk; //时钟信号
32 input rst_n; //复位信号
33 output SPI_CS; //片选信号
34 input SPI_MISO; //SPI输入信号
35 output SPI_MOSI; //MOSI输出信号
36 output SPI_SCK; //SPI时钟输出信号
37 //-- 上级系统通信
38 input SPI_EN; //SPI通信使能信号
39 output SPI_Done; //采集结束标志
40 input SPI_SCK_CPOL; //时钟极性设置
41 input SPI_SCK_CPHA; //时钟相位设置
42 input [3:0]SPI_SCK_Freq_Sel; //时钟频率选择信号
43 input [4:0]SPI_Rx_Data_Width; //将接收数据位宽
44 output[15:0]SPI_Rx_Data; //输出采集数据
45 input [4:0]SPI_Tx_Data_Width; //发送数据位宽
46 input [15:0]SPI_Tx_Data; //待发送数据
47 //-------------------------------------------------------------------
48 //-- 模块例化
49 //-------------------------------------------------------------------
50 SPI_CTL SPI_CTL(
51 .clk(clk),
52 .rst_n(rst_n),
53 .SPI_EN(SPI_EN),
54 .SPI_Done(SPI_Done),
55 .SPI_SCK_CPOL(SPI_SCK_CPOL),
56 .SPI_SCK_CPHA(SPI_SCK_CPHA),
57 .SPI_SCK_Freq_Sel(SPI_SCK_Freq_Sel),
58 .SPI_Rx_Data_Width(SPI_Rx_Data_Width),
59 .SPI_Rx_Data(SPI_Rx_Data),
60 .SPI_Tx_Data_Width(SPI_Tx_Data_Width),
61 .SPI_Tx_Data(SPI_Tx_Data),
62 .SPI_CS(SPI_CS),
63 .SPI_MOSI(SPI_MOSI),
64 .SPI_MISO(SPI_MISO),
65 .SPI_SCK(SPI_SCK)
66 );
67 endmodule
附上仿真图两张
前仿真

后仿真


浙公网安备 33010602011771号