99在线精品免费视频九九视-99在线精品视频-99在线精品视频免费观里-99在线精品视频在线观看-99在线免费播放



官方論壇
官方淘寶
官方博客
微信公眾號(hào)
點(diǎn)擊聯(lián)系吳工 點(diǎn)擊聯(lián)系周老師
您的當(dāng)前位置:主頁(yè) > FPGA入門基礎(chǔ) >

至簡(jiǎn)設(shè)計(jì)法之SPI接口設(shè)計(jì)-明德?lián)P科教(mdy-edu.com)

發(fā)布時(shí)間:2019-12-10   作者:admin 瀏覽量:

SPI(Serial Peripheral Interface--串行外設(shè)接口)總線系統(tǒng)是一種同步串行外設(shè)接口,它可以使MCU與各種外圍設(shè)備以串行方式進(jìn)行通信以交換信息。本項(xiàng)目我們通過(guò)SPI接口實(shí)現(xiàn)FPGAEEPROM芯片——AT93C46的通信。示意圖如圖3-16

fpga就業(yè)

3-16 SPI接口傳輸結(jié)構(gòu)圖

先查閱AT93C46datasheet,了解各引腳的作用。

cs:從器件使能信號(hào),由主器件控制;

sk:時(shí)鐘信號(hào),由主器件產(chǎn)生;

do:主器件數(shù)據(jù)輸入,從器件數(shù)據(jù)輸出;

di:主器件數(shù)據(jù)輸出,從器件數(shù)據(jù)輸入。

再明確實(shí)現(xiàn)相互通信需要哪些操作。

1. 三種基本的操作

1EWEN時(shí)序(圖3-17

3-17 EWEN時(shí)序圖

EWEN可以理解為激活設(shè)備,寫、擦除(這里沒有用到,有興趣的讀者可以自行查閱datasheet)操作執(zhí)行之前必須要先執(zhí)行完EWEN操作。其操作過(guò)程為:

1) cs在開始操作時(shí)拉高,等到讀操作完成,拉低;

2) skCS拉高時(shí),產(chǎn)生10個(gè)脈沖,脈沖周期大于400ns

3) diSK的周期內(nèi)輸出數(shù)據(jù),前面輸出固定的指令“10011”,指示是EWEN操作,后面則繼續(xù)輸出5比特的“0”

2WRITE時(shí)序(圖3-18

3-18 WRITE時(shí)序圖

寫操作:

1) cs先拉高一段時(shí)間,然后再拉低TCS時(shí)間,最后再拉高CS,直至檢測(cè)到DO1,拉低;

2) skCS第一段拉高時(shí),產(chǎn)生18個(gè)脈沖,脈沖周期大于400ns

3) disk的周期內(nèi)輸出數(shù)據(jù),前面輸出固定的指令“101”,指示是寫操作,后面則繼續(xù)輸出地址“AN~A0”和數(shù)據(jù)“DN~D0”

3READ時(shí)序(圖3-19

fpga就業(yè)前景

3-19 ERAD時(shí)序圖

1) cs在開始操作時(shí)拉高,等到讀操作完成,拉低;

2) skcs第一段拉高時(shí),產(chǎn)生18個(gè)脈沖,脈沖周期大于400ns

3) disk的周期內(nèi)輸出數(shù)據(jù),前面輸出固定的指令“110”,指示是讀操作,后面則繼續(xù)輸出地址“AN~A0”和固定的“0”

4) 模塊從sk的第11個(gè)周期開始從do中讀取數(shù)據(jù),每個(gè)周期讀取1比特,共8比特。

實(shí)現(xiàn)一個(gè)AT93C46的接口,該接口能夠根據(jù)命令,實(shí)現(xiàn)EWENWRITEREAD功能。具體功能如下:

明德?lián)P在變化范圍內(nèi)取了1us作為tcs的值;AT93C46時(shí)鐘取1MHz

上游模塊在rdy=1時(shí),給出start命令,開始進(jìn)行EWENWRITE或者READ操作。在rdy=0期間,start命令無(wú)效。

當(dāng)start有效時(shí),如果mode=0表示進(jìn)行EWEN操作;mode=1表示進(jìn)行WRITE操作;mode=2表示進(jìn)行READ操作。

當(dāng)start有效時(shí),addrwdata有效。

當(dāng)進(jìn)行EWEN操作時(shí),模塊將按at93c46 EWEN的要求,將addr寫入at93c46

當(dāng)進(jìn)行WRITE操作時(shí),模塊將按at93c46 WRITE的要求,將addrwdata寫入at93c46

當(dāng)進(jìn)行READ操作時(shí),模塊將按at93c46 READ的要求,將addr寫入at93c46,并從at93c46讀到數(shù)據(jù),通過(guò)rdatardata_vld返回給上游模塊。

2. 設(shè)計(jì)過(guò)程

1明確功能

根據(jù)題目可以畫出設(shè)備與AT93C46之間的具體通信框圖如圖3-20

3-20 信號(hào)傳輸架構(gòu)圖

3.5 信號(hào)列表

至簡(jiǎn)設(shè)計(jì)法

(2)輸出分析

cs:在WRITE操作時(shí),寫入一個(gè)地址和數(shù)據(jù)后拉低,間隔tcs拉高,等待寫操作完成;READ操作和EWEN操作都是在操作期間為高,操作結(jié)束拉低。

sk:引入計(jì)數(shù)器,通過(guò)計(jì)數(shù)產(chǎn)生1MHz的芯片時(shí)鐘。

rdy:從操作開始到結(jié)束一直為低電平,其他時(shí)刻為高電平。

di:根據(jù)操作的不同輸出相應(yīng)的值

rdata:僅在READ操作時(shí)do的值從高位到低位,一比特一比特地給rdata賦值。

rdata_vld:在rdata賦值結(jié)束后,拉高一個(gè)時(shí)鐘周期,表示此時(shí)rdata有效。

3狀態(tài)劃分

EWENREADWRITE的時(shí)序圖我們可以發(fā)現(xiàn)在不同操作中有很多階段是相似的,總結(jié)起來(lái)有4個(gè)狀態(tài):

IDLE:初始狀態(tài),模塊在等待start信號(hào)有效。

WR_RD:讀寫狀態(tài)。

TCS:片選信號(hào)拉低。

DO:等待寫入操作完成。

4狀態(tài)轉(zhuǎn)移

狀態(tài)轉(zhuǎn)移圖請(qǐng)見3-21

至簡(jiǎn)設(shè)計(jì)法

3-21 狀態(tài)轉(zhuǎn)移圖


5轉(zhuǎn)移條件

確定了狀態(tài)轉(zhuǎn)移圖后,我們需要明確狀態(tài)轉(zhuǎn)移條件:

wr_rd_start:在IDLE狀態(tài)下收到start有效。

tcs_start:在WR_RD狀態(tài)結(jié)束。

idle_start1:,處于EWENREAD模式,在TCS狀態(tài)結(jié)束(1us)。

do_start:處于WRITE模式,在TCS結(jié)束(1us)。

idle_start2:處于WRITE模式,在TCS狀態(tài)下,收到do==1


6完整性檢查

至簡(jiǎn)設(shè)計(jì)法

7狀態(tài)機(jī)代碼

第一段,用同步時(shí)序,將次態(tài)的值賦給現(xiàn)態(tài)。注意此時(shí)直接套用模塊,不要做任何更改。

1 always  @(posedge clk or negedge rst_n)begin
2     if(rst_n==1'b0)begin
3         state_c <= IDLE;
4     end
5     else begin
6         state_c <=state_n; 
7     end
8 end

第二段,用組合邏輯描述狀態(tài)轉(zhuǎn)移條件。注意轉(zhuǎn)移條件用信號(hào)來(lái)表示,信號(hào)名要按明德?lián)P規(guī)則來(lái)命名。

 1 always  @(*)begin
 2     case(state_c)
 3         IDLE:begin
 4             if(idl2wrd_start)begin
 5                 state_n = WR_RD;
 6             end
 7             else begin
 8                 state_n = state_c;
 9             end
10         end
11         WR_RD:begin
12             if(wrd2tcs_start)begin
13                 state_n = TCS;
14             end
15             else begin
16                 state_n = state_c;
17             end
18         end
19         TCS:begin
20             if(tcs2do_start)begin
21                 state_n = DO;
22             end
23             else if(tcs2idl_start)begin
24                 state_n = IDLE;
25             end
26             else begin
27                 state_n = state_c;
28             end
29         end
30         DO:begin
31             if(do2idl_start)begin
32                 state_n = IDLE;
33             end
34             else begin
35                 state_n = state_c;
36             end
37         end
38         default:begin
39             state_n = IDLE;
40         end
41     endcase
42 end
43

第三段,用assign定義轉(zhuǎn)移條件。注意條件一定要加上現(xiàn)態(tài)。

1 assign idl2wrd_start = state_c == IDLE && start == 1;
2 assign wrd2tcs_start = state_c == WR_RD&& end_cnt1;
3 assign tcs2idl_start = state_c == TCS && end_cnt
4                        && (mode_reg==EWEN||mode_reg==READ);
5 assign tcs2do_start = state_c == TCS && mode_reg == WRITE && end_cnt;
6 assign do2idl_start = state_c == DO && mode_reg == WRITE && do_ff1 == 1;

第四段,則是輸出信號(hào)設(shè)計(jì),在功能代碼部分。

8功能代碼

  1 //根據(jù)第六步第1點(diǎn),寫出cnt的代碼
  2 always  @(posedge clk or negedge rst_n)begin
  3     if(rst_n==1'b0)begin
  4         cnt <= 0;
  5     end
  6     else if(add_cnt) begin
  7         if(end_cnt)
  8             cnt <= 0;
  9         else
 10             cnt <= cnt + 1;
 11     end
 12 end
 13 assign  add_cnt = state_c == WR_RD || state_c == TCS;
 14 assign  end_cnt = add_cnt && cnt==100 - 1 ;
 15
 16 //根據(jù)第六步第2點(diǎn),寫出cnt1的代碼
 17 always  @(posedge clk or negedge rst_n)begin
 18     if(rst_n==1'b0)begin
 19         cnt1<= 0;
 20     end
 21     else if(add_cnt1) begin
 22         if(end_cnt1)
 23             cnt1 <= 0;
 24         else
 25             cnt1 <= cnt1 + 1;
 26     end
 27 end
 28 assign  add_cnt1 = end_cnt;
 29 assign  end_cnt1 = add_cnt1 && cnt1==x -1 ;
 30
 31 always  @(*)begin
 32     if(mode_reg == EWEN)begin
 33         x = 10;
 34     end
 35     else if(mode_reg == WRITE)begin
 36         x = 18;
 37     end
 38     else if(mode_reg == READ)begin
 39         x = 18;
 40     end
 41     else begin
 42         x = 0;
 43     end
 44 end
 45 //根據(jù)第六步第3點(diǎn),寫出do的代碼
 46 always  @(posedge clk or negedge rst_n)begin
 47     if(rst_n==1'b0)begin
 48         do_ff0<=0;
 49         do_ff1<=0;
 50     end
 51     else begin
 52         do_ff0<=d0;
 53         do_ff1<=do_ff0;
 54     end
 55 end
 56
 57 //根據(jù)第六步第4點(diǎn),寫出sk的代碼
 58 always  @(posedge clk or negedge rst_n)begin
 59     if(rst_n==1'b0)begin
 60         sk <= 0;
 61     end
 62     else if(sk_high)begin
 63         sk <= 1;
 64     end
 65     else if(sk_low)begin
 66         sk <= 0;
 67     end
 68 end
 69 assign sk_high = state_c == WR_RD && add_cnt && cnt == 50-1;
 70 assign sk_low = state_c == WR_RD && end_cnt;
 71
 72 //根據(jù)第六步第5點(diǎn),寫出di的代碼
 73 always  @(posedge clk or negedge rst_n)begin
 74     if(rst_n==1'b0)begin
 75         di <= 0;
 76     end
 77     else if(di_en)begin
 78         di <= dout[17-cnt1];
 79     end
 80 end
 81 assign di_en = cnt==0 && state_c == WR_RD;
 82
 83 //根據(jù)第六步第6點(diǎn),寫出cs的代碼
 84 always  @(posedge clk or negedge rst_n)begin
 85     if(rst_n==1'b0)begin
 86         cs <= 0;
 87     end
 88     else if(cs_high)begin
 89         cs <= 1;
 90     end
 91     else if(cs_low)begin
 92         cs <= 0;
 93     end
 94 end
 95 assign cs_high = idl2wrd_start || tcs2do_start;
 96 assign cs_low = wrd2tcs_start || do2idl_start; 
 97
 98 //根據(jù)第六步第7點(diǎn),寫出rdy的代碼
 99 always  @(*)begin
100     if(rdy_low)
101         rdy = 0;
102     else 
103         rdy = 1;
104 end
105 assign rdy_low = start || state_c != IDLE;  
106
107 //根據(jù)第六步第8點(diǎn),寫出rdata的代碼
108 always  @(posedge clk or negedge rst_n)begin
109     if(rst_n==1'b0)begin
110         rdata <= 0;
111     end
112     else if(rdata_en)begin
113         rdata <=  {rdata[6:0],do};
114     end
115 end
116 assign rdata_en = mode_reg == READ && state_c == WR_RD && end_cnt
117 && cnt1 >= 10 && cnt1 < 18;
118
119 //根據(jù)第六步第9點(diǎn),寫出rdata_vld的代碼
120 always  @(posedge clk or negedge rst_n)begin
121     if(rst_n==1'b0)begin
122         rdata_vld <= 0;
123     end
124     else if(rdata_vld_en)begin
125         rdata_vld <= 1;
126     end
127     else begin
128         rdata_vld <= 0;    
129     end
130 end
131 assign rdata_vld_en = mode_reg == READ && wrd2tcs_start;
132
133 //根據(jù)第六步第10點(diǎn),寫出dout的代碼
134 always  @(posedge clk or negedge rst_n)begin
135     if(rst_n==1'b0)begin
136         dout <= 0;
137     end
138     else if(start && mode==0)begin
139         dout <= {3'b100,2’b11,13'b0};
140     end
141     else if(start && mode==1)begin
142         dout <= {3'b101,addr,wdata};
143     end
144     else if(start && mode==2)begin
145         dout <= {3'b110,addr,8'b0};
146     end
147 end
148
149 always  @(posedge clk or negedge rst_n)begin
150     if(rst_n==1'b0)begin
151         mode_reg <= 0;
152     end
153     else if(start && mode==0)begin
154         mode_reg <= EWEN;
155     end
156     else if(start && mode==1)begin
157         mode_reg <= WRITE;
158     end
159     else if(start && mode==2)begin
160         mode_reg <= READ;
161     end
162 end
163

技術(shù)交流QQ群:544453837

更多FPGA技術(shù)資訊:明德?lián)P科教

點(diǎn)擊了解>>至簡(jiǎn)設(shè)計(jì)法


  •   
  •   
  •   
  •  
  • FPGA教育領(lǐng)域第一品牌
  • 咨詢熱線:020-39002701
  • 技術(shù)交流Q群:544453837
主站蜘蛛池模板: 青草精品视频 | 欧美黄免在线播放 | 美女xx网站 | 丝袜美腿秘书ol在线播放 | 亚洲国产精品一区二区三区久久 | 永久免费不卡在线观看黄网站 | 欧美成视频人免费淫片 | 九九99视频在线观看视频观看 | 亚洲欧洲精品成人久久曰影片 | 国产成人精品免费视频大全办公室 | 手机看片亚洲 | 日韩欧美不卡一区二区三区 | 99视频精品免视3 | 日韩精品永久免费播放平台 | 久久怡红院亚欧成人影院 | 国产精品亚洲专区在线播放 | 国产在线一91区免费国产91 | 欧美一级一一特黄 | 欧美特级毛片a够爽天狼影院 | 色综合久久88色综合天天 | 在线亚洲日产一区二区 | 在线 欧美| 亚洲伊人影院 | 中文字幕日韩精品亚洲七区 | 香蕉视频黄色 | 亚洲人成在线观看一区二区 | 精品一区二区三区在线观看 | 一区二区在线免费视频 | 免费在线一区二区三区 | 黄色毛片网站 | 精品视频久久久 | 久久久久国产成人精品亚洲午夜 | 国产精品亚洲综合网站 | 黄色视屏日本 | 激情欧美成人狠狠色金八天国 | 久久国产免费一区二区三区 | 麻豆国产一区二区在线观看 | 国产精品夜色视频一区二区 | 97国内精品久久久久久久影视 | 日本 wwwwwxxxxx | 国产精品一区二区不卡的视频 |