SPI主机Verilog代码实现
前面已经提到过了SPI,在SPI从机的设计中已经讲过SPI的基本原理,这里就不再赘述。对于SPI的主机可以参考百度百科或则笔者前面写的SPI从机介绍的相关知识。
下面是SPI_master的代码
SPI_master.v
1 //**************************************************************************
2 // *** file name : SPI_master.v
3 // *** version : 1.0
4 // *** Description : SPI master timing generation, supports four SPI modes
5 // *** Blogs :
6 // *** Author : Galois_V
7 // *** Date : 2022.02.14
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module SPI_master
12 #(
13 parameter TX_WIDTH = 16 ,
14 parameter RX_WIDTH = 16
15 )
16 (
17 input i_sys_clk ,
18 input i_sys_rstn ,
19 output reg o_spi_cs ,
20 output reg o_spi_sclk ,
21 output o_spi_mosi ,
22 input i_spi_miso ,
23 input i_spi_cpol ,
24 input i_spi_cpha ,
25 input i_spi_start ,
26 output o_spi_state ,
27 input [15:0] i_spi_rate ,
28 input [1:0] i_spi_ctrl ,
29 input i_spi_tx_valid ,
30 input [TX_WIDTH-1:0] i_spi_tx_data ,
31 output o_spi_tx_req ,
32 output o_spi_rx_valid ,
33 output [RX_WIDTH-1:0] o_spi_rx_data
34 );
35 wire w_sclk_edge_over ;
36 wire w_spi_read_en ;
37 wire w_spi_write_en ;
38 wire w_spi_sclk_reverse_en;
39 wire w_spi_rx_valid ;
40 reg r_spi_over ;
41 reg r_spi_state_en ;
42 reg r_spi_start ;
43 reg [15:0] r_sclk_edge_cnt ;
44 reg r_spi_get_state ;
45 reg r_spi_over_dly ;
46 reg [15:0] r_spi_sclk_cnt ;
47 reg [3:0] r_spi_sclk_bit_cnt;
48 reg [TX_WIDTH-1:0] r_spi_tx_data ;
49 reg [2:0] r_spi_rx_en ;
50 reg [RX_WIDTH-1:0] r_spi_rx_data ;
51 reg [2:0] r_spi_miso ;
52 reg [3:0] r_spi_rx_valid ;
53 localparam EDGE_CNT = TX_WIDTH * 2 - 1;
54 assign w_spi_read_en = i_spi_ctrl[0];
55 assign w_spi_write_en = i_spi_ctrl[1];
56 always@(posedge i_sys_clk)
57 begin
58 if(~i_sys_rstn)
59 begin
60 r_spi_start <= 'd0;
61 end
62 else
63 begin
64 r_spi_start <= i_spi_start;
65 end
66 end
67 always@(posedge i_sys_clk)
68 begin
69 if(~i_sys_rstn)
70 begin
71 r_spi_state_en <= 'd0;
72 end
73 else if(r_spi_over)
74 begin
75 r_spi_state_en <= 'd0;
76 end
77 else if(r_spi_start)
78 begin
79 r_spi_state_en <= 1'b1;
80 end
81 end
82 assign o_spi_state = ~r_spi_state_en;
83 /******************************************************************************\
84 sclk edge count
85 \******************************************************************************/
86 always@(posedge i_sys_clk)
87 begin
88 if(~i_sys_rstn)
89 begin
90 r_sclk_edge_cnt <= 'd0;
91 end
92 else if(r_spi_start)
93 begin
94 r_sclk_edge_cnt <= 'd0
95 end
96 else if(r_spi_over)
97 begin
98 r_sclk_edge_cnt <= r_sclk_edge_cnt;
99 end
100 else if(w_sclk_edge_over)
101 begin
102 r_sclk_edge_cnt <= r_sclk_edge_cnt + 1'b1;
103 end
104 end
105 always@(posedge i_sys_clk)
106 begin
107 if(~i_sys_rstn)
108 begin
109 r_spi_over <= 'd0;
110 end
111 else if (w_sclk_edge_over & (r_sclk_edge_cnt == EDGE_CNT))
112 begin
113 r_spi_over <= 1'b1;
114 end
115 else
116 begin
117 r_spi_over <= 'd0;
118 end
119 end
120 always@(posedge i_sys_clk)
121 begin
122 if(~i_sys_rstn)
123 begin
124 r_spi_get_state <= 'd0;
125 end
126 else if(r_spi_get_state & i_spi_tx_valid | r_spi_over)
127 begin
128 r_spi_get_state <= 'd0;
129 end
130 else if(w_spi_write_en & r_spi_start)
131 begin
132 r_spi_get_state <= 1'b1;
133 end
134 end
135 assign o_spi_tx_req = (~r_spi_over & r_spi_get_state & i_spi_valid) & w_spi_write_en;
136 /******************************************************************************\
137 Generate SPI CS
138 \******************************************************************************/
139 always@(posedge i_sys_clk)
140 begin
141 if(~i_sys_rstn)
142 begin
143 r_spi_over_dly <= 'd0;
144 end
145 else
146 begin
147 r_spi_over_dly <= r_spi_over;
148 end
149 end
150 always@(posedge i_sys_clk)
151 begin
152 if(~i_sys_rstn)
153 begin
154 o_spi_cs <= 'd1;
155 end
156 else if(r_spi_over_dly)
157 begin
158 o_spi_cs <= 1'b1;
159 end
160 else if(i_spi_start)
161 begin
162 o_spi_cs <= 'd0;
163 end
164 end
165 /******************************************************************************\
166 Generatte SPI sclk
167 \******************************************************************************/
168 always@(posedge i_sys_clk)
169 begin
170 if(~i_sys_rstn)
171 begin
172 r_spi_sclk_cnt <= 'd0;
173 end
174 else if(r_spi_start | w_spi_sclk_reverse_en)
175 begin
176 r_spi_sclk_cnt <= 'd0;
177 end
178 else
179 begin
180 r_spi_sclk_cnt <= r_spi_sclk_cnt + 1'b1;
181 end
182 end
183 assign w_spi_sclk_reverse_en = (r_spi_sclk_cnt == i_spi_rate);
184 always@(posedge i_sys_clk)
185 begin
186 if(~i_sys_rstn)
187 begin
188 r_spi_sclk_bit_cnt <= 'd0;
189 end
190 else if(r_spi_start | r_spi_over)
191 begin
192 r_spi_sclk_bit_cnt <= 'd0;
193 end
194 else if(w_spi_sclk_reverse_en)
195 begin
196 r_spi_sclk_bit_cnt <= r_spi_sclk_bit_cnt + 1'b1;
197 end
198 end
199 assign w_sclk_edge_over = w_spi_sclk_reverse_en & r_spi_state_en;
200 /******************************************************************************\
201 SPI MODE
202 \******************************************************************************/
203 always@(posedge i_sys_clk)
204 begin
205 if(~i_sys_rstn)
206 begin
207 o_spi_sclk <= 'd0;
208 end
209 else if(r_spi_start)
210 begin
211 o_spi_sclk <= i_spi_cpol ^ i_spi_cpha;
212 end
213 else if(~r_spi_state_en | ((r_sclk_edge_cnt== EDGE_CNT) & w_sclk_edge_over))
214 begin
215 o_spi_sclk <= i_spi_cpol;
216 end
217 else if(w_spi_sclk_reverse_en)
218 begin
219 o_spi_sclk <= ~o_spi_sclk;
220 end
221 end
222 /******************************************************************************\
223 Generate SPI MOSI
224 \******************************************************************************/
225 always@(posedge i_sys_clk)
226 begin
227 if(~i_sys_rstn)
228 begin
229 r_spi_tx_data <= 'd0;
230 end
231 else if(o_spi_tx_req)
232 begin
233 r_spi_tx_data <= i_spi_tx_data;
234 end
235 else if(r_spi_state_en & r_spi_sclk_bit_cnt[0] & w_spi_sclk_reverse_en)
236 begin
237 r_spi_tx_data <= r_spi_tx_data << 1;
238 end
239 end
240 assign o_spi_mosi = r_spi_tx_data[TX_WIDTH-1];
241 /******************************************************************************\
242 Generate SPI MISO
243 \******************************************************************************/
244 always@(posedge i_sys_clk)
245 begin
246 if(~i_sys_rstn)
247 begin
248 r_spi_miso <= 'd0;
249 end
250 else
251 begin
252 r_spi_miso <= {r_spi_miso[1:0],i_spi_miso};
253 end
254 end
255 always@(posedge i_sys_clk)
256 begin
257 if(~i_sys_rstn)
258 begin
259 r_spi_rx_en <= 'd0;
260 end
261 else
262 begin
263 r_spi_rx_en <= {r_spi_rx_en[1:0],(r_spi_state_en & (~r_spi_sclk_bit_cnt[0]) & w_spi_sclk_reverse_en)};
264 end
265 end
266 always@(posedge i_sys_clk)
267 begin
268 if(~i_sys_rstn)
269 begin
270 r_spi_rx_data <= 'd0;
271 end
272 else if(r_spi_rx_en[2])
273 begin
274 r_spi_rx_data <= {r_spi_rx_data[RX_WIDTH-2:0],r_spi_miso[2]};
275 end
276 end
277 assign o_spi_rx_data = r_spi_rx_data;
278 /******************************************************************************\
279 SPI valid delay 4clock ensure data stability
280 \******************************************************************************/
281 always@(posedge i_sys_clk)
282 begin
283 if(~i_sys_rstn)
284 begin
285 r_spi_rx_valid <= 'd0;
286 end
287 else
288 begin
289 r_spi_rx_valid <= {r_spi_rx_valid[2:0],w_spi_rx_valid};
290 end
291 end
292 assign w_spi_rx_valid = w_sclk_edge_over & (r_sclk_edge_cnt == EDGE_CNT) & w_spi_read_en;
293 assign o_spi_rx_valid = r_spi_rx_valid[3];
294 endmodule
这里提下,笔者写代码比较喜欢写通用点的代码,这里速率是可以控制,不过最大只能是系统时钟的1/4,SPI的模式也支持4种模式,start信号在这里是占一个系统时钟的脉冲信号。至于代码是否没问题,笔者不能保证,笔者在仿真测试中还未曾发现有太大问题,也仅供参考。这里可以用AXI4_lite总线来对该模块代码进行按需控制,可以把例化的参数CLK_EDGE也用总线配置。
SPI主机Verilog代码实现的更多相关文章
- Verilog代码规范I
Verilog代码规范I "规范"这问题 "规范"这个富含专业气息的词汇(个人感觉),其实规范这种东西,就是大家都约定熟成的东西,一旦你不遵守这个东西,专业人士 ...
- HD,3G视频数据中行号的插入方法---Verilog代码实现
HD,3G视频数据中行号的插入方法---Verilog代码实现 行号的生成: `timescale 1ns / 1ps //////////////////////////////////////// ...
- 串口接收端verilog代码分析
串口接收端verilog代码分析 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////// ...
- 串口发送端verilog代码分析
串口发送端verilog代码分析 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////// ...
- verilog 代码分析与仿真
verilog 代码分析与仿真 注意:使用vivado 自带的仿真工具, reg和wire等信号需要赋予初始值 边沿检测 module signal_test( input wire cmos_pcl ...
- 总线读写---verilog代码
总线读写---verilog代码 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////// ...
- FIFO 的控制逻辑---verilog代码
FIFO 的控制逻辑---verilog代码 //fifo的例化 wire fifo_full; wire fifo_empty; : ] fifo_dout; :]rd_data_count; :] ...
- 信号滤波模块verilog代码---UNLOCK,LOCK状态机方式
信号滤波模块verilog代码 `timescale 1ns / 1ps /////////////////////////////////////////////////////////////// ...
- verilog代码 想法验证---与寄存器输出有关
verilog代码 想法验证---与寄存器输出有关 1. module test_mind( input wire clk, input wire reset, input wire i, outpu ...
- 时钟分频方法---verilog代码
时钟分频方法---verilog代码 本文以SDI播出部分的工程为例,来说明一种时钟分频的写法.SD-SDI工程中播出时钟tx_usrclk为148.5MHz,但tx_video_a_y_in端的数据 ...
随机推荐
- 代码随想录算法训练营day17 | leetcode ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和
LeetCode 110.平衡二叉树 分析1.0 求左子树高度和右子树高度,若高度差>1,则返回false,所以我递归了两遍 class Solution { public boolean is ...
- PostGIS之几何创建函数
1. 概述 PostGIS 是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在 SQL 中运行空间查询 PostGIS官网:About PostGIS | PostGIS ...
- C# WCF实现聊天室功能
1.WCF是什么 Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架 看这篇文章之前,可以先看我的另一篇文章,初步了解一下WCF: ...
- LeetCode-1669 合并两个链表
来源:力扣(LeetCode)链接:https://leetcode.cn/problems/merge-in-between-linked-lists 题目描述 给你两个链表 list1 和 lis ...
- Flutter 下载篇 - 贰 | 当下载器遇上切换网络库
需求背景 继上篇<Flutter 下载篇 - 壹 | flutter_download_manager 源码解析>中详细介绍了 flutter_download_manager 用法和原理 ...
- 免费ASP空间
free免费asp空间的申请方法: free免费asp空间的ftp使用方法: sise.host3v.vip/1
- Spring Cloud Stream 消息驱动
屏蔽底层消息中间件的差异,降低切换成本 , 统一消息的编程模型. 通过定义绑定器Binder 作为中间件. 实现应用程序与消息中间件的细节之间的隔离. 消息发送端: <dependencies& ...
- 淘宝sign算法和使用教程
前言 最新写的淘宝热卖插件系列里面有涉及到淘宝sign算法加密,这里博主分享一下之前找到算法和修改后的算法以及使用教程.在此希望能帮助更多的人,欢迎各位加入我的交流Q群:468458543,群内不定时 ...
- mysql创建存储过程造数据
delimiter $$$ DROP PROCEDURE zqtest6; create procedure zqtest6() begin declare i int default 0; set ...
- 支持批量图片转文字的【OCR】文字识别工具,支持截图识别,速度快,准确度高,免费OCR,开源软件
想必大家偶尔也有需要从图片中提取文字的需求,虽然现在手机上都自带了拍照识别功能,可是从电脑上的图片传到手机识别再将结果发回来实 在是有点麻烦,尤其当图片数量较多时,更是费时费力,使用网页版工具又要面临 ...