《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 其他 > 業(yè)界動(dòng)態(tài) > FPGA三段式狀態(tài)機(jī)的思維陷阱

FPGA三段式狀態(tài)機(jī)的思維陷阱

2022-07-14
來源:FPGA設(shè)計(jì)論壇
關(guān)鍵詞: FPGA三段式 狀態(tài)機(jī)

FPGA三段式描述狀態(tài)機(jī)是否完全正確?FPGA三段式描述有沒有思維陷阱呢?讓我們一起來解讀一下FPGA三段式狀態(tài)機(jī)的思維邏輯,。



       用三段式描述狀態(tài)機(jī)的好處,,國內(nèi)外各位大牛都已經(jīng)說的很多了,大致可歸為以下三點(diǎn):

  1.將組合邏輯和時(shí)序邏輯分開,,利于綜合器分析優(yōu)化和程序維護(hù);

  2.更符合設(shè)計(jì)的思維習(xí)慣;

  3.代碼少,比一段式狀態(tài)機(jī)更簡潔。

  對于第一點(diǎn),,我非常認(rèn)可,后兩點(diǎn)在Clifford E. Cummings著的(Synthesizable Finite State Machine Design Techniques Using theNew SystemVerilog 3.0 Enhancements和The Fundamentals ofEfficient Synthesizable Finite State Machine Design using NC-Verilog andBuildGates)中多次提到,,我并不完全贊同,,下面談?wù)勎业囊恍┛捶ā?/p>

  先談?wù)劦诙c(diǎn)關(guān)于思維習(xí)慣。我發(fā)現(xiàn)有些人會(huì)有這樣一種習(xí)慣,,先用一段式狀態(tài)機(jī)實(shí)現(xiàn)功能,,仿真ok后,再將其轉(zhuǎn)成三段式,,他們對這種開發(fā)方式的解釋是一段式更直觀,,可以更便捷的構(gòu)建功能框架,但是大家都說三段式性能會(huì)更好,,所以最后又在搭好的邏輯框架下,,將一段式轉(zhuǎn)化為了三段式。這從一個(gè)側(cè)面說明了,,對一部人來說一段式更符合他們的思維習(xí)慣,,但當(dāng)已經(jīng)習(xí)慣了一段式的思維方式后,再要換用三段式時(shí),,可就不這么容易了,,一段式和三段式的寫法之間存在著思維陷阱,,特權(quán)同學(xué)也曾經(jīng)不小心在此失足過。

  舉一個(gè)例子,,初始狀態(tài)是wr_st,,q和p輸出都為0,當(dāng)計(jì)數(shù)器count計(jì)數(shù)到指定的數(shù)值10后,,輸出結(jié)束信號end,,狀態(tài)機(jī)接收到end有效后跳轉(zhuǎn)為 rd_st,同時(shí)輸出q變?yōu)?,在rd_st狀態(tài),,如jump有效則跳轉(zhuǎn)到erase_st,,如end有效p輸出0否則輸出1,用一段式實(shí)現(xiàn)起來很簡單,,如下所示,。

  assign end = (count == 10);

  always @(posedge clk)

  begin

  case(state)

  wr_st:  if(end) begin

  q     <= 1;

  state<= rd_st;

  end

  else  begin

  q     <= 0;

  state<= wr_st;

  end

  rd_st:  if(jump) begin

  p     <=1;

  state<= erase_st;

  end

  elseif(end) begin

  p     <=  0;

  state<= rd_st;

  end

  else  begin

  p     <=  1;

  state<= rd_st;

  end

  ...

  endcase

  end

  狀態(tài)機(jī)一

  輸出波形如下所示。

  圖一

  換用三段式描述時(shí),,有些人會(huì)寫成這樣,。

  always @(posedge clk or negedge rst)

  begin

  if(!rst) state <= wr_st;

  else     state <=nextstate;

  end

  always @(*)

  begin

  case(state)

  wr_st: if(end)  nextstate = rd_st;

  else     nextstate = wr_st;

  rd_st: if(jump) nextstate = erase_st

  else     nextstate = rd_st;

  ...

  end

  endcase

  always @(posedge clk)

  begin

  case(nextstate)

  wr_st: if(end) q <= 1;

  else    q<= 0;

  rd_st:  if(end) p <= 0;

  else   p <= 1;

  ...

  endcase

  end

  狀態(tài)機(jī)二

  看似代碼好像沒有什么問題,但從輸出波形可以看出,,q沒有正確輸出,。

  圖二

  上圖中狀態(tài)轉(zhuǎn)移正確,但是q輸出錯(cuò)誤,,nextstate由組合邏輯輸出,,當(dāng)end有效后,nextstate立刻變?yōu)閞d_st,導(dǎo)致A時(shí)刻q沒有變化,,在將一段式改為三段式的過程中,,我們?nèi)员A袅艘欢问降乃季S習(xí)慣,想當(dāng)然的利用了end信號去控制狀態(tài)跳轉(zhuǎn),,同時(shí)又控制了q的輸出,,這種思維誤區(qū)由以下兩點(diǎn)對三段式狀態(tài)機(jī)的認(rèn)知缺陷構(gòu)成。

  1.書本網(wǎng)上大部分狀態(tài)機(jī)例程的第三段都是基于nextstate輸出的,,很少看到有基于state輸出的,,這就形成了一種思維定勢,認(rèn)為三段式的第三段只能基于nextstate描述,。

  2.當(dāng)三段式狀態(tài)機(jī)的輸出基于nextstate描述時(shí),,無法用同一個(gè)輸入信號即觸發(fā)當(dāng)前狀態(tài)跳轉(zhuǎn),又控制當(dāng)前狀態(tài)輸出正確邏輯,,上述例子中A時(shí)刻q的錯(cuò)誤輸出印證了這一點(diǎn),,end可以觸發(fā)狀態(tài)從wr_st跳轉(zhuǎn)到rd_st,但無法同時(shí)讓q輸出1,。

  有兩種解決辦法,。

  第一種解決辦法是增加狀態(tài),,將wr_st拆分為wr_st0和wr_st1兩個(gè)狀態(tài),end信號只控制狀態(tài)跳轉(zhuǎn),,q的輸出跟隨wr_st0和wr_st1變化,,第一段不變,如下所示

  always @(*)

  begin

  case(state)

  wr_st0: if(end)  nextstate = wr_st1;

  else     nextstate = wr_st0;

  wr_st1:             nextstate= rd_st;

  rd_st:  if(jump) nextstate = erase_st;

  else      nextstate = rd_st;

  ...

  end

  endcase

  always @(posedge clk)

  begin

  case(nextstate)

  wr_st0:          q<= 0;

  wr_st1:          q<= 1;

  rd_st: if(end) p <= 0;

  else   p <= 1;

  ...

  endcase

  end

  狀態(tài)機(jī)三

  更改后波形輸出正確,,如圖一所示,。有些人會(huì)覺得這種方式?jīng)]有一段式直觀,數(shù)據(jù)手冊標(biāo)明的協(xié)議只有寫和讀兩個(gè)狀態(tài),,為什么用三段式狀態(tài)機(jī)描述時(shí)還要增加一個(gè)狀態(tài)呢,?反而有一種拼湊時(shí)序的感覺,;另一些人會(huì)覺得這種思維方式很自然,,協(xié)議里只有兩個(gè)狀態(tài),但是每個(gè)狀態(tài)里又會(huì)有不同的輸出,,根據(jù)輸入和輸出的不同可以將一個(gè)狀態(tài)解剖為多個(gè)細(xì)分狀態(tài),,狀態(tài)分的越細(xì),越利于綜合工具分析優(yōu)化,,但是狀態(tài)太多了也不利于人員的查看維護(hù),。將這個(gè)問題延展開,目前網(wǎng)站書籍中講解狀態(tài)機(jī)的例子都以"狀態(tài)多,,輸出少"為主,,這種類型的狀態(tài)機(jī),不用太多考慮狀態(tài)劃分問題,,直接用moor型就ok了,,不過,現(xiàn)實(shí)工作中我們還會(huì)遇到很多"狀態(tài)少,,輸出多"的情況,,那該如何劃分狀態(tài)呢?

  一幫人會(huì)覺得狀態(tài)少更直觀,,使用盡量少的狀態(tài),,把所有跟當(dāng)前狀態(tài)相關(guān)的輸出都寫在同一個(gè)狀態(tài)里,這種習(xí)慣會(huì)傾向于寫成一段式或者mealy型,;

  一幫人覺得如果一個(gè)狀態(tài)里的輸出太多了不利于理解,,會(huì)使用盡量多的狀態(tài),每一個(gè)狀態(tài)只對應(yīng)一種輸出,,這種習(xí)慣會(huì)將狀態(tài)機(jī)傾向?qū)懗蒻oor型,。

  如換用上文的例程,主張狀態(tài)少的幫派會(huì)寫成一段式的狀態(tài)機(jī)一,,或?qū)懗慑e(cuò)誤的狀態(tài)機(jī)二,,主張多狀態(tài)的幫派會(huì)寫成狀態(tài)機(jī)三,,從性能方面考慮,后者將狀態(tài)細(xì)分的更清楚,,綜合工具會(huì)更容易優(yōu)化分析,,獲得更好的性能,但是綜合工具altera和xilinx每年都在更新,,分析能力也越來越強(qiáng),,越來越聰明,減少開發(fā)者的經(jīng)驗(yàn)門檻,,按這種趨勢,,前者和后者的性能差異也會(huì)逐年縮小。從維護(hù)升級的方面考慮,,前者和后者的輸出都一樣,,但是前者的狀態(tài)少,代碼會(huì)更少些,,更利于查看,,對代碼理解上面,本來就存在兩種不同的思維習(xí)慣,,只能智者見智了,。

  回到本例中,第二種解決辦法是,,僅將狀態(tài)機(jī)二的第三段的nextstate換成state,,其他兩段不變,如下所示,。

  always @(posedge clk)

  begin

  case(state)

  wr_st: if(end) q <= 1;

  else       q<= 0;

  rd_st: if(end)  p <= 0;

  else       p<= 1;

  ...

  endcase

  end

  輸出波形和一段式相同,,如圖一所示,三段式狀態(tài)機(jī)的第三段并沒有規(guī)定一定要基于nextstate輸出,,只是主流資料在介紹三段式狀態(tài)機(jī)時(shí),,多用moor型為例,moor型的特點(diǎn)是輸出僅由狀態(tài)決定,,當(dāng)狀態(tài)變化時(shí),,輸出立刻變化,如要實(shí)現(xiàn)輸出緊跟著狀態(tài)變化,,第三段中就必須要基于nextstate輸出才可以,,對比圖一和圖二B時(shí)刻,使用state時(shí),,當(dāng)前狀態(tài)已經(jīng)變?yōu)閞d_st,,輸出p滯后了一個(gè)時(shí)鐘才輸出,而使用nextstate時(shí),當(dāng)前狀態(tài)變?yōu)?rd_st的同時(shí)輸出p就變化了,,再比較圖一和圖二的C時(shí)刻,,在同一個(gè)狀態(tài)下,end有效后,,兩者的p輸出都一樣,,所以可得出,第三段使用nextstate和state的區(qū)別在于,,當(dāng)狀態(tài)跳轉(zhuǎn)時(shí),,基于nextstate的輸出是立刻變化的,而基于state輸出會(huì)延遲一個(gè)周期,,其他情況都一樣,,應(yīng)該根據(jù)自己的時(shí)序要求,選擇用nextstate還是state,。

  這里提到的三段式的思維陷阱,,特權(quán)同學(xué)曾經(jīng)也不小心犯過,所著的《深入淺出玩轉(zhuǎn)FPGA》的p40,,漫談狀態(tài)機(jī)設(shè)計(jì)一節(jié)中舉了sram的例子比較一段式和三段式的區(qū)別,,一段式是可以按照程序正常運(yùn)行的,但是三段式的輸出在讀取的狀態(tài)下會(huì)和一段式略有不同,,當(dāng)cstate進(jìn)入RD_S1時(shí),如果此時(shí)wr_req有效,,cmd不會(huì)輸出3`b101,,而是3`b111,問題在于使用了 wr_req同時(shí)控制了RD_S1的跳轉(zhuǎn)和cmd輸出,,RD_S2也存在同樣的問題,,如下所示。

  case(cstate)

  ...

  RD_S1: if(wr_req) nstate <=WR_S2;

  else         nstate <= RD_S2;

  RD_S2: if(wr_req) nstate <=WR_S1;

  else         nstate <= IDLE;

  ...

  endcase

  ...

  case(nstate)

  ...

  WR_S2: cmd <= 3'b111;

  RD_S1: if(wr_req)  cmd <=3'b101;

  else          cmd <= 3'b110;

  RD_S2: if(wr_req)  cmd <=3'b011;

  else         cmd <= 3'b111;

  ...

  endcase

  再回到開篇,,談?wù)劦谌c(diǎn)關(guān)于代碼量,,Clifford E. Cummings在文中提到一段式狀態(tài)機(jī)會(huì)比三段式狀態(tài)機(jī)會(huì)多20%到80%的代碼量,并舉例證明,。但是舉得例子都有一個(gè)特點(diǎn)"狀態(tài)多,,輸出少",比如有 10種狀態(tài),,但是輸出種類只有5種,,很多的狀態(tài)都是相同的輸出,這在第三段式描述時(shí)就可以利用case的簡寫語法減少代碼量,,如下所示

  case (next)

  S0, S2, S4, S5 : ; // defaultoutputs

  S7             :   y3<= 1'b1;

  S1             :   y2<= 1'b1;

  S3             :begin

  y1<= 1'b1;

  y2<= 1'b1;

  end

  S8             :begin

  y2<= 1'b1;

  y3<= 1'b1;

  end

  S6,S9         : begin

  y1<= 1'b1;

  y2<= 1'b1;

  y3<= 1'b1;

  end

  endcase

  但是實(shí)際的狀態(tài)機(jī)中,,還有很多是“狀態(tài)少,輸出多”的情況,,每種狀態(tài)都會(huì)有不同的輸出,,這就無法利用上述的case的簡寫語法了,,再試著比較一下,一段式和三段式的輸出邏輯代碼量幾乎一樣,,狀態(tài)轉(zhuǎn)移部分也差不多,,但是在輸入判斷代碼量方面,一段式只用判斷一次可完成狀態(tài)轉(zhuǎn)移和輸出,,對于mealy型,,第二段和第三段都要判斷,這就肯定比一段式多了,,對于moor型,,第二段需要判斷一次,第三段雖然不用判斷但是為了實(shí)現(xiàn)相同的功能肯定要將狀態(tài)擴(kuò)展,,相比一段式增加了不少的代碼量,。所以不能一概而論一段式的代碼量就一定比三段式多,要視具體情況而定,。

  


 更多信息可以來這里獲取==>>電子技術(shù)應(yīng)用-AET<<


本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn),。轉(zhuǎn)載的所有的文章,、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有,。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容、版權(quán)和其它問題,,請及時(shí)通過電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失,。聯(lián)系電話:010-82306118,;郵箱:[email protected]