lcytms
发表于 2017-2-7 16:49:18
下面将在SPI状态机模块的基础上,再加上并转串移位寄存器、选择器、计数器等三个模块。
lcytms
发表于 2017-2-7 16:49:56
主控端(Master)SPI程序模块图。
lcytms
发表于 2017-2-7 16:51:19
本帖最后由 lcytms 于 2017-2-7 16:56 编辑
新建spi_write.v文件。
切换顶层模块为spi_write.v文件。
module spi_write (CLK,SPC,SDAT,regdata,GO,ORDY,reset,SCEN);
input CLK;
input GO;
input reset;
input regdata;
inout SDAT;
output SPC;
output SCEN;
output ORDY;
reg Q;
reg bitcount;
wire LDEN, SHEN, rstbitcount;
wire bitcountEN;
wire SCLK;
spi_three_wire spi0 (
.reset(reset),
.CLK(CLK),
.GO(GO),
.bitcount(bitcount),
.bitcountEN(bitcountEN),
.rstbitcount(rstbitcount),
.LDEN(LDEN),
.SHEN(SHEN),
.SCLK(SCLK),
.SCEN(SCEN),
.ORDY(ORDY),
.SPC(SPC)
);
always @ (posedge CLK or posedge reset)
begin
if (reset)
bitcount <= 0;
else
begin
if (rstbitcount)
bitcount <= 0;
else
begin
if (bitcountEN)
bitcount <= bitcount + 4'd1;
end
end
end
always @ (posedge CLK or posedge reset)
begin
if (reset)
Q <= 0;
else
begin
if (LDEN)
Q <= regdata;
else
begin
if (SHEN)
Q <= {Q, 1'b0};
end
end
end
assign SDAT = (SCEN || SCLK) ? 1'bz : Q;
endmodule
lcytms
发表于 2017-2-7 16:57:23
本帖最后由 lcytms 于 2017-2-7 17:00 编辑
进行分析综合检查。
编写Testbench。
新建spi_write_test.v文件。
`timescale 1ns/1ns
module spi_write_test;
reg CLK;
reg GO;
reg reset;
reg regdata;
wire SDAT;
wire SPC;
wire SCEN;
wire ORDY;
spi_write dut (CLK,SPC,SDAT,regdata,GO,ORDY,reset,SCEN);
initial
begin
CLK = 0;
reset = 1;
GO = 0;
regdata = 16'b1010100z_10101010;
#100
reset = 0;
GO = 1;
#100
GO = 0;
#2000 $stop;
end
always #50 CLK = ~CLK;
endmodule
lcytms
发表于 2017-2-7 17:06:12
进行分析综合检查。
进行仿真设置。
查看仿真结果。
当SCEN为0时,SPC的时钟有16个上升沿。
当传输结束时,SCEN为1,且ORDY为1。
SDA输出的值为1010100z_10101010,高位在前。
仿真功能正确。
lcytms
发表于 2017-2-7 17:07:35
好了,今天的课程就讲到这里。
通过今天的课程,我们学习了SPI串行外设接口的基本原理,并对SPI逻辑电路进行了建模、仿真。
后续课程中的AD、12864等部分均用到了基于SPI协议的器件,届时我们会结合具体器件向大家演示SPI协议的具体应用。
希望大家掌握SPI的基本原理,熟练运用Verilog语言编写相关驱动逻辑。
更复杂的知识和技巧我们将逐步通过后面的课程展现给大家。
课程到此结束,谢谢大家的关注!
星云通
发表于 2018-9-27 17:38:26
感谢李老师提供的资料,讲解很详细
fpga_feixiang
发表于 2018-9-28 15:05:33
顶~~~~~~~~~~~~~
cwj0123
发表于 2020-5-26 14:44:42
感謝老師熱心講解SPI相關知識~~~~真得很用心