SPI(Serial Peripheral Interface--串行外(wài)設接口(kǒu))總(zǒng)線(xiàn)系(xì)統是(shì)一(yī)種(zhǒng)同(tóng)步串行外(wài)設接口(kǒu),它(tā)可(kě)以(yǐ)使MCU與(yǔ)各(gè)種(zhǒng)外(wài)圍設備以(yǐ)串行方(fāng)式進(jìn)行通(tòng)信(xìn)以(yǐ)交換信(xìn)息。本(běn)項目我(wǒ)们(men)通(tòng)过(guò)SPI接口(kǒu)实現(xiàn)FPGA與(yǔ)EEPROM芯片(piàn)——AT93C46的(de)通(tòng)信(xìn)。示意(yì)图(tú)如(rú)图(tú)3-16。
图(tú)3-16 SPI接口(kǒu)傳輸結構图(tú)
sk:时(shí)鐘(zhōng)信(xìn)号(hào),由(yóu)主(zhǔ)器件(jiàn)産生(shēng);
do:主(zhǔ)器件(jiàn)數據(jù)輸入(rù),從器件(jiàn)數據(jù)輸出(chū);
di:主(zhǔ)器件(jiàn)數據(jù)輸出(chū),從器件(jiàn)數據(jù)輸入(rù)。
(1)EWEN时(shí)序(图(tú)3-17)
图(tú)3-17 EWEN时(shí)序图(tú)
EWEN可(kě)以(yǐ)理解(jiě)为(wèi)激活設備,写、擦除(这(zhè)里(lǐ)沒(méi)有(yǒu)用(yòng)到(dào),有(yǒu)興趣的(de)读(dú)者(zhě)可(kě)以(yǐ)自(zì)行查閱datasheet)操作執行之前(qián)必須要(yào)先(xiān)執行完EWEN操作。其操作过(guò)程为(wèi):
1.cs在(zài)開(kāi)始操作时(shí)拉高(gāo),等到(dào)读(dú)操作完成(chéng),拉低;
2.sk在(zài)CS拉高(gāo)时(shí),産生(shēng)10个(gè)脈沖,脈沖周期(qī)大于(yú)400ns;
3.di在(zài)SK的(de)周期(qī)內(nèi)輸出(chū)數據(jù),前(qián)面(miàn)輸出(chū)固定(dìng)的(de)指令“10011”,指示是(shì)EWEN操作,後(hòu)面(miàn)則繼續輸出(chū)5比特(tè)的(de)“0”。
(2)WRITE时(shí)序(图(tú)3-18)
图(tú)3-18 WRITE时(shí)序图(tú)
写操作:
(1)cs先(xiān)拉高(gāo)一(yī)段(duàn)时(shí)間(jiān),然後(hòu)再拉低TCS时(shí)間(jiān),最(zuì)後(hòu)再拉高(gāo)CS,直(zhí)至(zhì)檢测到(dào)DO为(wèi)1,拉低;
(2)sk在(zài)CS第(dì)一(yī)段(duàn)拉高(gāo)时(shí),産生(shēng)18个(gè)脈沖,脈沖周期(qī)大于(yú)400ns;
(3)di在(zài)sk的(de)周期(qī)內(nèi)輸出(chū)數據(jù),前(qián)面(miàn)輸出(chū)固定(dìng)的(de)指令“101”,指示是(shì)写操作,後(hòu)面(miàn)則繼續輸出(chū)地(dì)址“AN~A0”和(hé)數據(jù)“DN~D0”。
(3)READ时(shí)序(图(tú)3-19)
图(tú)3-19 ERAD时(shí)序图(tú)
(1)cs在(zài)開(kāi)始操作时(shí)拉高(gāo),等到(dào)读(dú)操作完成(chéng),拉低;
(2)sk在(zài)cs第(dì)一(yī)段(duàn)拉高(gāo)时(shí),産生(shēng)18个(gè)脈沖,脈沖周期(qī)大于(yú)400ns;
(3)di在(zài)sk的(de)周期(qī)內(nèi)輸出(chū)數據(jù),前(qián)面(miàn)輸出(chū)固定(dìng)的(de)指令“110”,指示是(shì)读(dú)操作,後(hòu)面(miàn)則繼續輸出(chū)地(dì)址“AN~A0”和(hé)固定(dìng)的(de)“0”;
(4)模块(kuài)從sk的(de)第(dì)11个(gè)周期(qī)開(kāi)始從do中(zhōng)读(dú)取(qǔ)數據(jù),每个(gè)周期(qī)读(dú)取(qǔ)1比特(tè),共(gòng)8比特(tè)。
明(míng)德揚在(zài)變(biàn)化(huà)範圍內(nèi)取(qǔ)了(le)1us作为(wèi)tcs的(de)值;AT93C46时(shí)鐘(zhōng)取(qǔ)1MHz。
上(shàng)遊模块(kuài)在(zài)rdy=1时(shí),給(gěi)出(chū)start命令,開(kāi)始進(jìn)行EWEN、WRITE或(huò)者(zhě)READ操作。在(zài)rdy=0期(qī)間(jiān),start命令无效。
當start有(yǒu)效时(shí),如(rú)果(guǒ)mode=0表(biǎo)示進(jìn)行EWEN操作;mode=1表(biǎo)示進(jìn)行WRITE操作;mode=2表(biǎo)示進(jìn)行READ操作。
2. 設計(jì)过(guò)程
(1)明(míng)确功能(néng)
根(gēn)據(jù)題(tí)目可(kě)以(yǐ)画(huà)出(chū)設備與(yǔ)AT93C46之間(jiān)的(de)具體(tǐ)通(tòng)信(xìn)框图(tú)。如(rú)图(tú)3-20。
图(tú)3-20 信(xìn)号(hào)傳輸架構图(tú)
表(biǎo)3.5 信(xìn)号(hào)列表(biǎo)
(2)輸出(chū)分(fēn)析
di:根(gēn)據(jù)操作的(de)不(bù)同(tóng)輸出(chū)相應(yìng)的(de)值
(3)狀态劃(huà)分(fēn)
(4)狀态轉(zhuǎn)移
狀态轉(zhuǎn)移图(tú)請見(jiàn)3-21。
图(tú)3-21 狀态轉(zhuǎn)移图(tú)
(5)轉(zhuǎn)移条(tiáo)件(jiàn)
确定(dìng)了(le)狀态轉(zhuǎn)移图(tú)後(hòu),我(wǒ)们(men)需要(yào)明(míng)确狀态轉(zhuǎn)移条(tiáo)件(jiàn):
wr_rd_start:在(zài)IDLE狀态下(xià)收(shōu)到(dào)start有(yǒu)效。
tcs_start:在(zài)WR_RD狀态結束(shù)。
idle_start1:,处于(yú)EWEN或(huò)READ模式,在(zài)TCS狀态結束(shù)(1us)。
do_start:处于(yú)WRITE模式,在(zài)TCS結束(shù)(1us)。
idle_start2:处于(yú)WRITE模式,在(zài)TCS狀态下(xià),收(shōu)到(dào)do==1。
(6)完整性(xìng)檢查
(7)狀态機(jī)代(dài)碼
第(dì)二(èr)段(duàn),用(yòng)組合邏輯描述狀态轉(zhuǎn)移条(tiáo)件(jiàn)。注意(yì)轉(zhuǎn)移条(tiáo)件(jiàn)用(yòng)信(xìn)号(hào)来(lái)表(biǎo)示,信(xìn)号(hào)名要(yào)按明(míng)德揚規則来(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
第(dì)三(sān)段(duàn),用(yòng)assign定(dìng)義轉(zhuǎn)移条(tiáo)件(jiàn)。注意(yì)条(tiáo)件(jiàn)一(yī)定(dìng)要(yào)加上(shàng)現(xiàn)态。
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;
7
第(dì)四(sì)段(duàn),則是(shì)輸出(chū)信(xìn)号(hào)設計(jì),在(zài)功能(néng)代(dài)碼部(bù)分(fēn)。
(8)功能(néng)代(dài)碼
1 //根(gēn)據(jù)第(dì)六(liù)步第(dì)1點(diǎn),写出(chū)cnt的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)2點(diǎn),写出(chū)cnt1的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)3點(diǎn),写出(chū)do的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)4點(diǎn),写出(chū)sk的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)5點(diǎn),写出(chū)di的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)6點(diǎn),写出(chū)cs的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)7點(diǎn),写出(chū)rdy的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)8點(diǎn),写出(chū)rdata的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)9點(diǎn),写出(chū)rdata_vld的(de)代(dài)碼
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 //根(gēn)據(jù)第(dì)六(liù)步第(dì)10點(diǎn),写出(chū)dout的(de)代(dài)碼
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
温(wēn)馨提(tí)示:明(míng)德揚2023推出(chū)了(le)全(quán)新課程——邏輯設計(jì)基本(běn)功修煉課,降低学習FPGA門(mén)檻的(de)同(tóng)时(shí),增加了(le)学習的(de)趣味性(xìng),并組織了(le)考試赢積分(fēn)活動(dòng)
http://www.minyingyiyuan.com/ffkc/415.html
(點(diǎn)擊→了(le)解(jiě)課程詳情(qíng)☝)感(gǎn)興趣請聯系(xì)易老(lǎo)师(shī):13112063618(微信(xìn)同(tóng)步)







