赞
踩
SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。
本文以SPI Master控制器为例来对Verilog源码进行分析,参考资料为《VERILOG HDL应用程序设计实例精讲》,仅供学习参考,项目在文章末尾给出下载链接。
1、时钟分频模块,将原始时钟进行四分频,过程较为简单,不再详述。
module clkdiv(clk,clkout); input clk; output clkout; reg [1:0]cnt=2'd0; reg clkout=1'b0; always @(posedge clk)begin if(cnt==2'd1)begin clkout<=1'b1; cnt<=cnt+2'd1; end else if(cnt == 2'd3)begin clkout<=1'b0; cnt<=2'd0; end else begin cnt<=cnt+2'd1; end end endmodule
2、SPI发送数据部分,在spiclk的上升沿完成数据的传输。spics为片选信号,低有效;spido为输出的数据;dstate为FSM变量。dsend为待传送数据,其中部分数据过程重复,代码中仅保留首尾数据的传输过程。
begin case (dstate) 8'd0: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd1; end 8'd1: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd2; end 8'd2: begin spics <= 1'b0; spiclk <= 1'b0; spido <= 1'b1; dstate <= 8'd3; end 8'd3: begin spics <= 1'b0; spiclk <= 1'b1; spido <= dsend[7]; dstate <= 8'd4; end 8'd4: begin spics <= 1'b0; spiclk <= 1'b0; spido <= dsend[7]; dstate <= 8'd5; end …… 8'd17: begin spics <= 1'b0; spiclk <= 1'b1; spido <= dsend[0]; dstate <= 8'd18; end 8'd18: begin spics <= 1'b0; spiclk <= 1'b0; spido <= dsend[0]; dstate <= 8'd19; end 8'd19: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd20; end 8'd20: begin spics <= 1'b0; spiclk <= 1'b1; spido <= 1'b1; dstate <= 8'd0; spistate <= idle; end endcase end default: begin spics <= 1'b1; spiclk <= 1'b1; spido <= 1'b1; spistate <= 2'b00; end endcase end
可以看到当片选信号spics为低有效时,数据在spiclk的上升沿按顺序被发送至SPI总线上,数据信号spido与输入数据相对应,SPI Master发送时序得到验证。
3、SPI接收数据部分,参数定义与2一样,其中部分数据过程重复,代码中仅保留首尾数据的传输过程。在时钟的下降沿进行数据的接收。
begin case (dstate) 8'd0: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd1; end 8'd1: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd2; end 8'd2: begin spics <= 1'b0; spiclk <= 1'b0; dstate <= 8'd3; end 8'd3: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd4; end 8'd4: begin spics <= 1'b0; spiclk <= 1'b0; dreceive[7] <= spidi; dstate <= 8'd5; end 8'd5: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd6; end …… 8'd18: begin spics <= 1'b0; spiclk <= 1'b0; dreceive[0] <= spidi; dstate <= 8'd19; end 8'd19: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd20; dataout <= dreceive; end 8'd20: begin spics <= 1'b0; spiclk <= 1'b1; dstate <= 8'd0; spistate <= 2'b00; end endcase end
由上图分析看出,收到的数据与SPI传输的数据相对应,SPI接收数据部分得到正确验证。
实验项目框图:
实验心得:
1、在给复位信号低电平时时间过短,分频后时钟上升沿还未到复位信号就拉高了,导致未进行有效复位。
2、进行发送/接收状态检测时设置的计数子过大,如下图,每过40个时钟周期进行一次检测,当仿真时间过短时,容易看不到结果。
if(cnt == 8'd40) begin cnt <= 8'd0; if((wr == 1'b0) && (rd == 1'b1)) begin spistate <= send_data; dstate <= 8'd0; dsend <= datain; end else if((wr == 1'b1) && (rd == 1'b0)) begin spistate <= receive_data; dstate <= 8'd0; end end else begin cnt <= cnt + 8'd1; end
3、若结果出现问题,将相关控制信号添加至窗口,观察其状态,分析程序存在的问题。
参考资料:https://blog.csdn.net/weixin_42509369/article/details/83096349
《VERILOG HDL应用程序设计实例精讲》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。