SPI(Serial Peripheral Interface),是一种同步的传输协定,主要应用於单晶片系统中。类似 I2C(之後会提到),它的应用有快闪记忆体、EEPROM、SD 卡与显示器等等....
SPI协定规定了4个逻讯号介面(也有三线的,但那就是单工了):
开始传输资料时,CS 要拉低,而我的模式是:mosi 在 SCLK 的负缘时值会改变,而 miso 则是在 SCLK 正缘时值会改变,与 Uart 不同的是:SPI 并没有起始位元,slave 单纯靠 SCLK 的正负缘读取资料(正或负要看如何设计的),在这边,资料位宽的话我是做 16bit;传输频率 1MHZ,因为想说可以试着与 max7219 做通讯,有兴趣的可以去查一下 max7219 的 datasheet。
跟 UART 一样,先定义四个状态:
/*---------parameter---------*/
localparam IDLE = 2'd0;
localparam START = 2'd1;
localparam SHIFT = 2'd2;
localparam STOP = 2'd3;
再来定义输入输出
输入:
输出:
module SPI(
clk_sys,
SCLK_temp,
tick_SPI,
rst_n,
SCLK,
CS,
count,
countEN,
rstcount,
ready,
finish,
SHEN,
LDEN
);
/*-----------ports declaration-----------*/
input clk_sys;
input SCLK_temp;
input rst_n;
input ready;
input tick_SPI;
input [3:0] count;
output CS;
output countEN;
output rstcount;
output SHEN;
output LDEN;
output finish;
output SCLK;
reg CS;
reg countEN;
reg rstcount;
reg SHEN;
reg LDEN;
reg finish;
wire SCLK;
/*-----------finish-----------*/
always@(posedge clk_sys or negedge rst_n)begin
if(!rst_n)begin
finish <= 1'b0;
end
else begin
if(fstate==STOP&&tick_SPI)finish <= 1'b1;
else finish <= 1'b0;
end
end
宣告跑状态的变数:
/*---------variables---------*/
reg [1:0] fstate;
状态逻辑:
/*-----------state-----------*/
always@(posedge clk_sys or negedge rst_n)begin
if(!rst_n)fstate <= IDLE;
else begin
case(fstate)
IDLE:begin
if(ready)fstate <= START;
else fstate <= IDLE;
end
START:begin
if(tick_SPI)fstate <= SHITF;
else fstate <= START;
end
SHITF:begin
if(count==4'd14&&tick_SPI)fstate <= STOP;
else fstate <= SHITF;
end
STOP:begin
if(tick_SPI)fstate <= IDLE;
else fstate <= STOP;
end
default:fstate <= IDLE;
endcase
end
end
输出逻辑:
/*-----------output-----------*/
always@(posedge clk_sys or negedge rst_n)begin
if(!rst_n)begin
CS <= 1'b1;
countEN <= 1'b0;
rstcount <= 1'b0;
SHEN <= 1'b0;
LDEN <= 1'b0;
end
else begin
if(tick_SPI)begin
case(fstate)
IDLE:begin
CS <= 1'b1;
countEN <= 1'b0;
rstcount <= 1'b0;
SHEN <= 1'b0;
LDEN <= 1'b0;
end
START:begin
CS <= 1'b0;
countEN <= 1'b0;
rstcount <= 1'b0;
SHEN <= 1'b0;
LDEN <= 1'b1;
end
SHITF:begin
CS <= 1'b0;
countEN <= 1'b1;
if(count==4'd14) rstcount <= 1'b1;
else if(count<4'd14)rstcount <= 1'b0;
else rstcount <= 1'b0;//prevent latch
SHEN <= 1'b1;
LDEN <= 1'b0;
end
STOP:begin
CS <= 1'b1;
countEN <= 1'b0;
rstcount <= 1'b0;
SHEN <= 1'b0;
LDEN <= 1'b0;
end
default:begin
CS <= 1'bx;
countEN <= 1'bx;
rstcount <= 1'bx;
SHEN <= 1'bx;
LDEN <= 1'bx;
end
endcase
end
else begin
CS <= CS;
countEN <= countEN;
rstcount <= rstcount;
SHEN <= SHEN;
LDEN <= LDEN;
end
end
end
endmodule
这里也一样,要数到 15 却 14 就结束是因为外部模组会延後一个 clk,如果 15 才停,那外部模组它数到 16 才停下,shift 的次数也会多一次,这种情况是我们不乐见的~!
那麽今天的的教学就到这边,下一篇我们会完成整个 SPI 模组~~~~
<<: Day19:终於要进去新手村了-javascript-回圈-break、continue
>>: Day19 - Interpreting Machines - 2 :使用 interpret API
这次非常久才发布学习纪录,因为最近当兵的关系,能学习的时间又被压缩了,但我还是会努力播出时间练习的。...
曼哈顿距离(Manhattan Distance) 假设你要从家里走到学校,行径的距离肯定不会是两点...
不知不觉也来到最後一篇啦! 第八步 在 codepen 上可以看到一些酷炫的汉堡选单 code ,但...
Future介面定义有get()方法以及isDone()方法,其目的就是在呼叫get()时看看能不能...
KubeEdge 使用心得 KubeEdge的使用导向应是以"云边协同"、&qu...