前面已经提到过了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代码实现的更多相关文章

  1. Verilog代码规范I

    Verilog代码规范I "规范"这问题 "规范"这个富含专业气息的词汇(个人感觉),其实规范这种东西,就是大家都约定熟成的东西,一旦你不遵守这个东西,专业人士 ...

  2. HD,3G视频数据中行号的插入方法---Verilog代码实现

    HD,3G视频数据中行号的插入方法---Verilog代码实现 行号的生成: `timescale 1ns / 1ps //////////////////////////////////////// ...

  3. 串口接收端verilog代码分析

    串口接收端verilog代码分析 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////// ...

  4. 串口发送端verilog代码分析

    串口发送端verilog代码分析 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////// ...

  5. verilog 代码分析与仿真

    verilog 代码分析与仿真 注意:使用vivado 自带的仿真工具, reg和wire等信号需要赋予初始值 边沿检测 module signal_test( input wire cmos_pcl ...

  6. 总线读写---verilog代码

    总线读写---verilog代码 `timescale 1ns / 1ps ////////////////////////////////////////////////////////////// ...

  7. FIFO 的控制逻辑---verilog代码

    FIFO 的控制逻辑---verilog代码 //fifo的例化 wire fifo_full; wire fifo_empty; : ] fifo_dout; :]rd_data_count; :] ...

  8. 信号滤波模块verilog代码---UNLOCK,LOCK状态机方式

    信号滤波模块verilog代码 `timescale 1ns / 1ps /////////////////////////////////////////////////////////////// ...

  9. verilog代码 想法验证---与寄存器输出有关

    verilog代码 想法验证---与寄存器输出有关 1. module test_mind( input wire clk, input wire reset, input wire i, outpu ...

  10. 时钟分频方法---verilog代码

    时钟分频方法---verilog代码 本文以SDI播出部分的工程为例,来说明一种时钟分频的写法.SD-SDI工程中播出时钟tx_usrclk为148.5MHz,但tx_video_a_y_in端的数据 ...

随机推荐

  1. Gold Transportation

    题目 百度 分析 很容易想到二分答案 然后考虑判定 条件很多,奇奇怪怪 那就上网络流吧 边权 \(\leq mid\) 两个城市连边 \(inf\) 源点与所有城市连边,边权为本城市有金矿量 城市与自 ...

  2. 基于IGServer的Web地图要素增删改查

    1. 引言 MapGIS IGServer 是中地数码的一款跨平台GIS 服务器产品,提供了空间数据管理.分析.可视化及共享服务 MapGIS IGServer的下载(试用)地址:MapGIS IGS ...

  3. AD域

    一.介绍 [域] 存放在 [活动目录] 存放在 [域控制器] 二.域和活动目录的规划 三.安装域控制器

  4. SQLServer 编程总结

    case的用途 case语句有四个关键字,缺一不可,分别是:case when then end,另外还有一个else.case 后面跟字段名(当在when后面出现字段名时,case里不能写出来),w ...

  5. I2C接口

    I2C是一种多向控制总线,它是由PHILIPS公司在二十世纪八十年代初设计出来的,利用该总线可实现多主机系统所需的裁决和高低速设备同步等功能,是一种高性能的串行总线.I2C总线只用两根双向传输线就可以 ...

  6. mysql explain 查看sql语句执行计划概述

    mysql explain 查看sql语句执行计划概述 id:选择标识符select_type:表示查询的类型.table:输出结果集的表partitions:匹配的分区type:表示表的连接类型po ...

  7. VMware-实用网站

    二进制包的获取方式 ftp://ftp.redhat.com推荐网站  www.rpmfind.net相应的官方网站http://www.mysql.com

  8. ORACLE 遇到ORA-31693 ORA-31617 ORA-19505 ORA-27037

    今天发现生产的RAC环境expdp计划任务出现报错 之前一度认为是备份目录权限的问题 官方文档: MOS参考文档:DataPump Export (EXPDP) Fails With Errors O ...

  9. 7.Object

    Object类 超类.基类,所以类的直接或间接父类,位于继承树的最顶层 任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承 Object类中所定义的方法,是所 ...

  10. 如何用adb连接android手机

    如何用adb连接android手机 以下为手机"root"情况下操作....手机没root请拉到笔记最后,有解决方法 利用adb来连接手机, 有两种方式: wifi usb 通过w ...