今天還是更新狀態機,狀態機基本是整個HDL中的核心,合理、高效地使用狀態機,是數字電路中的重要技能。
題目說明

圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, inputreset, input[3:1]s, outputfr3, outputfr2, outputfr1, outputdfr );
題目解析
moduletop_module( inputlogicclk, inputlogicreset, inputlogic[3:1]s, outputlogicfr3, outputlogicfr2, outputlogicfr1, outputlogicdfr ); //definestate typedefenumlogic[1:0]{empty=2'd0,level_1=2'd1,level_2=2'd2,level_3=2'd3}state_def; state_defcur_state,next_state; //describestatesequencerusesequentiallogic always_ff@(posedgeclk)begin if(reset)cur_state<=?empty?; ????????else???????cur_state?<=?next_state?; ???????? ????end ???//describe?next?state?decoder?use?conbinational?logic ???always_comb?begin? ???????unique?case?(s) ???????????3'b000:?next_state?=?empty?; ???????????3'd001:?next_state?=?level_1?; ???????????3'b011:?next_state?=?level_2?; ???????????3'b111:?next_state?=?level_3?;? ???????endcase ??????? ???end ???//describe?output?decoder?use?conbinational?and?sequential?logic ???//?decoder?output?fr1~fr3 ???assign?fr3?=?(cur_state?==?empty)?; ???assign?fr2?=?(cur_state?==?empty)?||?(cur_state?==?level_1)?;? ???assign?fr1?=?(cur_state?==?empty)?||?(cur_state?==?level_1)?||?(cur_state?==?level_2)?; ???//?decoder?output?dfr? ???var?logic?set_dfr?,?reset_dfr?; ???assign?set_dfr?=???((next_state?==?empty)?&&?(cur_state?!=?empty))?||? ??????????????????????((next_state?==?level_1)?&&?(cur_state?!=?level_1)?&&?(cur_state?!=?empty))?|| ??????????????????????((next_state?==?level_2)?&&?(cur_state?==?level_3))?; ???assign?reset_dfr?=?((next_state?==?level_3)?&&?(cur_state?!=?level_3))?||? ??????????????????????((next_state?==?level_2)?&&?(cur_state?!=?level_2)?&&?(cur_state?!=?level_3))?|| ??????????????????????((next_state?==?level_1)?&&?(cur_state?==?empty))?; ???????????????????? ???always_ff?@(?posedge?clk?)?begin? ?????????if?(reset)?begin ?????????????dfr?<=?1'd1?; ?????????end ?????????else?if?(set_dfr)?begin ?????????????dfr?<=?1'd1?; ?????????end ?????????else?if?(reset_dfr)?begin ?????????????dfr?<=?1'd0?; ?????????end ?????????else?begin ?????????????dfr?<=?dfr?; ?????????end ??????? ???end endmodule


點擊Submit,等待一會就能看到下圖結果:

注意圖中的Ref是參考波形,Yours是你的代碼生成的波形,網站會對比這兩個波形,一旦這兩者不匹配,仿真結果會變紅。
這一題就結束了。
Problem 127-Lemmings1
題目說明
旅鼠(Lemmings)游戲涉及相當簡單的小動物。所以我們將使用有限狀態機對其進行建模。
在 Lemmings 的 2D 世界中,Lemmings 可以處于兩種狀態之一:向左行走或向右行走。如果遇到障礙物,它會改變方向。
特別是,如果旅鼠在左邊被撞到,它就會向右走。
如果它被撞到右邊,它就會向左走。
如果它的兩側同時受到碰撞,它仍然會切換方向。
實現具有兩個狀態、兩個輸入和一個輸出的 Moore 狀態機來模擬此行為。


圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, inputareset,//FreshlybrainwashedLemmingswalkleft. inputbump_left, inputbump_right, outputwalk_left, outputwalk_right);
題目解析
我們首先需要找出狀態轉移規則。具體如下圖所示:

找到轉移關系后,后續的解答就和之前題目相同。
moduletop_module(
inputlogicclk,
inputlogicareset,//FreshlybrainwashedLemmingswalkleft.
inputlogicbump_left,
inputlogicbump_right,
outputlogicwalk_left,
outputlogicwalk_right);
//definestate
typedefenumlogic{left=1'b0,right=1'b1}state_def;
state_defstate,next_state;
//Statetransitionlogic
always_combbegin
case(state)
left:begin
if(bump_left)next_state=right;
elsenext_state=left;
end
right:begin
if(bump_right)next_state=left;
elsenext_state=right;
end
endcase
end
//Stateflip-flopswithasynchronousreset
always@(posedgeclk,posedgeareset)begin
if(areset)state<=?left?;
????????else??????????state?<=?next_state?;
????end
????//?Output?logic
????assign?walk_left?=?(state?==?left?);
????assign?walk_right?=?(state?==?right?);
endmodule

點擊Submit,等待一會就能看到下圖結果:

注意圖中的Ref是參考波形,Yours是你的代碼生成的波形,網站會對比這兩個波形,一旦這兩者不匹配,仿真結果會變紅。
這一題就結束了。
Problem 128-Lemmings2
題目說明
在上一題基礎上,除了左右行走之外,如果地面在它們下方消失,旅鼠還會掉落(并且大概會發出“啊啊!”)。
除了左右行走和碰撞時改變方向外,當ground=0時,旅鼠會倒下并說“啊啊!”。當地面重新出現 ( ground=1 ) 時,旅鼠將繼續沿與墜落前相同的方向行走。跌倒時被撞不影響行走方向,與地面消失(但尚未跌落)同周期被撞,或跌倒時地面再次出現,也不影響行走方向。
構建一個模擬此行為的有限狀態機。


圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, inputload, input[255:0]data, output[255:0]q); endmodule
題目解析
還是優先畫出狀態轉移圖:

moduletop_module(
inputlogicclk,
inputlogicareset,//FreshlybrainwashedLemmingswalkleft.
inputlogicbump_left,
inputlogicbump_right,
inputlogicground,
outputlogicwalk_left,
outputlogicwalk_right,
outputlogicaaah);
//definestate
typedefenumlogic[1:0]{left=2'd0,right=2'd1,fall_left=2'd2,fall_right=2'd3}state_def;
state_defcur_state,next_state;
//describestatetransitionuseconbinationallogic
always_combbegin
case(cur_state)
left:begin
if(!ground)begin
next_state=fall_left;
end
elseif(bump_left)begin
next_state=right;
end
elsebegin
next_state=left;
end
end
right:begin
if(!ground)begin
next_state=fall_right;
end
elseif(bump_right)begin
next_state=left;
end
elsebegin
next_state=right;
end
end
fall_left:begin
if(ground)begin
next_state=left;
end
elsebegin
next_state=fall_left;
end
end
fall_right:begin
if(ground)begin
next_state=right;
end
elsebegin
next_state=fall_right;
end
end
endcase
end
//describestatesequencerusesequentiallogic
always_ff@(posedgeclkorposedgeareset)begin
if(areset)begin
cur_state<=?left?;
????????end
????????else?begin
????????????cur_state?<=?next_state?;
????????end
????end
????
????//describe?output?decoder?use?conbinational?logic
????
????assign?walk_left?=?(cur_state?==?left)??;
????assign?walk_right?=?(cur_state?==?right);
????assign?aaah?=?(cur_state?==?fall_left)?||?(cur_state?==?fall_right)?;
????????
endmodule


點擊Submit,等待一會就能看到下圖結果:

注意圖中的Ref是參考波形,Yours是你的代碼生成的波形,網站會對比這兩個波形,一旦這兩者不匹配,仿真結果會變紅。
這一題就結束了。
Problem 129-Lemmings3
題目說明
在Lemmings1和Lemmings2基礎上。
除了行走和墜落之外,旅鼠有時會被告知做一些有用的事情,比如挖掘(它在dig=1時開始挖掘)。如果旅鼠當前正在地面上行走(ground=1且未掉落),則它可以挖掘,并且會繼續挖掘直到到達另一側(ground=0)。到那時,由于沒有地面,它會掉落(啊啊!),然后在它再次著地后繼續沿原來的方向行走。與掉落一樣,在挖掘時被碰撞沒有任何效果,而在掉落或沒有地面時被告知挖掘將被忽略。
(換句話說,行走的旅鼠可以掉落、挖掘或轉換方向。如果滿足其中一個以上條件,則掉落的優先級高于挖掘,而挖掘的優先級高于轉換方向。)
擴展您的有限狀態機來模擬這種行為。


圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, inputareset,//FreshlybrainwashedLemmingswalkleft. inputbump_left, inputbump_right, inputground, inputdig, outputwalk_left, outputwalk_right, outputaaah, outputdigging);
題目解析
狀態轉移圖:

moduletop_module(
inputlogicclk,
inputlogicareset,//FreshlybrainwashedLemmingswalkleft.
inputlogicbump_left,
inputlogicbump_right,
inputlogicground,
inputlogicdig,
outputlogicwalk_left,
outputlogicwalk_right,
outputlogicaaah,
outputlogicdigging);
//definestate
typedefenumlogic[2:0]{left=3'd0,right=3'd1,
fall_left=3'd2,fall_right=3'd3,
dig_left=3'd4,dig_right=3'd5}state_def;
state_defcur_state,next_state;
//describenextstatetransitionusecombinationallogic
always_combbegin
case(cur_state)
left:begin
if(!ground)begin
next_state=fall_left;
end
elseif(dig)begin
next_state=dig_left;
end
elseif(bump_left)begin
next_state=right;
end
elsebegin
next_state=left;
end
end
right:begin
if(!ground)begin
next_state=fall_right;
end
elseif(dig)begin
next_state=dig_right;
end
elseif(bump_right)begin
next_state=left;
end
elsebegin
next_state=right;
end
end
fall_left:begin
if(ground)begin
next_state=left;
end
elsebegin
next_state=fall_left;
end
end
fall_right:begin
if(ground)begin
next_state=right;
end
elsebegin
next_state=fall_right;
end
end
dig_left:begin
if(!ground)begin
next_state=fall_left;
end
elsebegin
next_state=dig_left;
end
end
dig_right:begin
if(!ground)begin
next_state=fall_right;
end
elsebegin
next_state=dig_right;
end
end
endcase
end
//describestatesequencerusesequentiallogic
always_ff@(posedgeclkorposedgeareset)begin
if(areset)begin
cur_state<=?left?;
????????end
????????else?begin
????????????cur_state?<=?next_state?;
????????end
????end
????//describe?ouput?decoder?use?combinational?logic
????assign?walk_left?=?(cur_state?==?left)?;
????assign?walk_right?=?(cur_state?==?right)?;
????assign?aaah?=?(cur_state?==?fall_left)?||?(cur_state?==?fall_right)?;
????assign?digging?=?(cur_state?==?dig_left)?||?(cur_state?==?dig_right)?;
endmodule


點擊Submit,等待一會就能看到下圖結果:

注意圖中的Ref是參考波形,Yours是你的代碼生成的波形,網站會對比這兩個波形,一旦這兩者不匹配,仿真結果會變紅。
這一題就結束了。
Problem 130-Lemmings4
題目說明
在Lemmings1、Lemmings2和Lemmings3基礎上:
盡管旅鼠可以行走、跌倒和挖掘,但旅鼠并非無懈可擊。如果旅鼠掉落的時間太長然后撞到地面,它可能會死亡。特別是,如果旅鼠掉落超過 20 個時鐘周期然后撞到地面,它將永遠停止行走、掉落或挖掘(所有 4 個輸出變為 0)(或直到 FSM 復位)。旅鼠在撞到地面之前可以跌落多遠沒有上限。旅鼠只會在撞到地面時死亡;它們不會死亡到半空中。
擴展之前的有限狀態機來模擬這種行為。

跌倒 20 個周期是可以生存的:

圖片來自HDLBits
下降 21 個周期會導致死亡:

圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, inputareset,//FreshlybrainwashedLemmingswalkleft. inputbump_left, inputbump_right, inputground, inputdig, outputwalk_left, outputwalk_right, outputaaah, outputdigging);
題目解析
狀態轉移圖:

moduletop_module(
inputlogicclk,
inputlogicareset,//FreshlybrainwashedLemmingswalkleft.
inputlogicbump_left,
inputlogicbump_right,
inputlogicground,
inputlogicdig,
outputlogicwalk_left,
outputlogicwalk_right,
outputlogicaaah,
outputlogicdigging);
//definestate
typedefenumlogic[2:0]{left=3'd0,right=3'd1,
fall_left=3'd2,fall_right=3'd3,
dig_left=3'd4,dig_right=3'd5,
splatter=3'd6,aaah_reset=3'd7
}state_def;
state_defcur_state,next_state;
varlogic[4:0]cycle_cout;
//describenextstatetransitionusecombinationallogic
always_combbegin
case(cur_state)
left:begin
if(!ground)begin
next_state=fall_left;
end
elseif(dig)begin
next_state=dig_left;
end
elseif(bump_left)begin
next_state=right;
end
elsebegin
next_state=left;
end
end
right:begin
if(!ground)begin
next_state=fall_right;
end
elseif(dig)begin
next_state=dig_right;
end
elseif(bump_right)begin
next_state=left;
end
elsebegin
next_state=right;
end
end
fall_left:begin
if(ground)begin
next_state=left;
end
elsebegin
if(cycle_cout==5'd20)begin
next_state=splatter;
end
elsebegin
next_state=fall_left;
end
end
end
fall_right:begin
if(ground)begin
next_state=right;
end
elsebegin
if(cycle_cout==5'd20)begin
next_state=splatter;
end
elsebegin
next_state=fall_right;
end
end
end
dig_left:begin
if(!ground)begin
next_state=fall_left;
end
elsebegin
next_state=dig_left;
end
end
dig_right:begin
if(!ground)begin
next_state=fall_right;
end
elsebegin
next_state=dig_right;
end
end
splatter:begin
if(ground)begin
next_state=aaah_reset;
end
elsebegin
next_state=splatter;
end
end
aaah_reset:begin
next_state=aaah_reset;
end
endcase
end
//describestatesequencerusesequentiallogic
always_ff@(posedgeclkorposedgeareset)begin
if(areset)begin
cur_state<=?left?;
????????????cycle_cout?<=?5'd0??;
????????end
????????else?begin
????????if?((next_state?==?fall_left)?||?(next_state?==?fall_right))?begin
????????????cycle_cout?<=?cycle_cout?+?5'd1?;
????????????cur_state?<=?next_state?;
????????end
????????else?begin
????????????cur_state?<=?next_state?;
????????????if(next_state?==?splatter)begin
????????????????cycle_cout?<=?cycle_cout?+?5'd1?;
????????????end
????????????else?begin
????????????????cycle_cout?<=?5'd0?;
????????????end
????????end
????????end
????????
????end
????//describe?ouput?decoder?use?combinational?logic
????assign?walk_left?=?(cur_state?==?left)?&&?(cur_state?!=?splatter)?;
????assign?walk_right?=?(cur_state?==?right)?&&?(cur_state?!=?splatter)?;
????assign?aaah?=?(cur_state?==?fall_left)?||?(cur_state?==?fall_right)?||?(cur_state?==?splatter)?;
????assign?digging?=?(cur_state?==?dig_left)?||?(cur_state?==?dig_right)?&&?(cur_state?!=?splatter)?;
endmodule

點擊Submit,等待一會就能看到下圖結果:

注意圖中的Ref是參考波形,Yours是你的代碼生成的波形,網站會對比這兩個波形,一旦這兩者不匹配,仿真結果會變紅。
這一題就結束了。
Problem 131-Fsm_onehot
題目說明
給定以下具有 1 個輸入和 2 個輸出的狀態機:

圖片來自HDLBits
假設這個狀態機使用 one-hot 編碼,其中state[0]到state[9]分別對應于狀態 S0 到 S9。除非另有說明,否則輸出為零。
實現狀態機的狀態轉換邏輯和輸出邏輯部分(但不是狀態觸發器)。在state[9:0]中獲得了當前狀態,并且必須生成next_state[9:0]和兩個輸出。
假設使用one-hot編碼,通過檢查推導出邏輯方程。(測試平臺將使用非熱輸入進行測試,以確保你不會嘗試做更復雜的事情)。
模塊端口聲明
moduletop_module( inputin, input[9:0]state, output[9:0]next_state, outputout1, outputout2);
題目解析
可以通過查看狀態轉換圖的轉移的路徑來導出獨熱碼狀態轉換邏輯的邏輯方程式。
仔細觀察發現在當前狀態state為正常獨熱碼(0x100, 0x1, 0x80)的時候,輸出的波形是正確的,但是輸入不是獨熱碼(0x900, 0x180)的時候,輸出就不正常了,這就是這道題所考察的地方,寫錯的同學自行翻看前一個獨熱碼狀態機的題目(Problem 125 fsm3onehot)再看正確答案。
//One-hotFSM??????IthinktheProblemhavesomeunreasonable moduletop_module( inputlogicin, inputlogic[9:0]state, outputlogic[9:0]next_state, outputlogicout1, outputlogicout2); //definestatebitposition parameterlogic[3:0]S0=0, S1=1, S2=2, S3=3, S4=4, S5=5, S6=6, S7=7, S8=8, S9=9; //describestatetransitionusecombinationallogic assignnext_state[S0]=~in&(state[S0]|state[S1]|state[S2]|state[S3]|state[S4]|state[S7]|state[S8]|state[S9]); assignnext_state[S1]=in&(state[S0]|state[S8]|state[S9]); assignnext_state[S2]=in&state[S1]; assignnext_state[S3]=in&state[S2]; assignnext_state[S4]=in&state[S3]; assignnext_state[S5]=in&state[S4]; assignnext_state[S6]=in&state[S5]; assignnext_state[S7]=in&(state[S6]|state[S7]); assignnext_state[S8]=~in&state[S5]; assignnext_state[S9]=~in&state[S6]; //describeoutputdecoderusecombinationallogic assignout1=state[S8]||state[S9]; assignout2=state[S7]||state[S9]; endmodule

點擊Submit,等待一會就能看到下圖結果:

注意圖中的Ref是參考波形,Yours是你的代碼生成的波形,網站會對比這兩個波形,一旦這兩者不匹配,仿真結果會變紅。
這一題就結束了。
Problem 132-Fsm_ps2
題目說明
PS/2 鼠標協議發送三個字節長的消息。但是,在連續的字節流中,消息的開始和結束位置并不明顯。唯一的跡象是每個三字節消息的第一個字節始終具有bit[3]=1(但其他兩個字節的 bit[3] 可能為 1 或 0,具體取決于數據)。
我們想要一個有限狀態機,它會在給定輸入字節流時搜索消息邊界。我們將使用的算法是丟棄字節,直到我們看到一個帶有bit[3]=1的字節。然后我們假設這是消息的第 1 個字節,并在接收到所有 3 個字節(完成)后發出消息接收信號。
FSM 應在成功接收到每條消息的第三個字節后立即在周期內發出完成信號。
一些時序圖來解釋所需的行為
在沒有錯誤的情況下,每三個字節組成一條消息:

圖片來自HDLBits
發生錯誤時,搜索字節 1:

請注意,這與1xx序列識別器不同。此處不允許重疊序列:

圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, input[7:0]in, inputreset,//Synchronousreset outputdone);
題目解析
盡管in[7:0]是一個字節,但狀態機使用一個輸入in[3]就夠了。
該狀態機可能有4個狀態,但其中的三種狀態沒有輸出是為了最后一個狀態輸出done桌準備。而對于接收到的某個消息,僅需一個時鐘周期即可判斷完成。
狀態圖。。。

moduletop_module(
inputlogicclk,
inputlogic[7:0]in,
inputlogicreset,//Synchronousreset
outputlogicdone);
typedefenumlogic[1:0]{S0=2'd0,S1=2'd1,S2=2'd2,Done=2'd3}state_def;
state_defcur_state,next_state;
//Statetransitionlogic(combinational)
always_combbegin
case(cur_state)
S0:begin
next_state=S1;
end
S1:begin
next_state=S2;
end
S2:begin
next_state=in[3]?S0:Done;
end
Done:begin
next_state=in[3]?S0:Done;
end
default:begin
next_state=Done;
end
endcase
end
//Stateflip-flops(sequential)
always_ff@(posedgeclk)begin
if(reset)begin
cur_state<=?Done?;
????????end
????????else?begin
????????????cur_state?<=?next_state?;
????????end
????????
????end
????//?Output?logic
????assign?done?=?(cur_state?==?S2)?;
endmodule

點擊Submit,等待一會就能看到下圖結果:

注意圖中無波形。
這一題就結束了。
Problem 133-Fsm_ps2data
題目說明
現在,已經寫了一個PS/2接口的狀態機,該狀態機可以標識PS/2字節流中的三字節消息。請在這個狀態機中添加一條數據路徑,該數據路徑可以在接收數據包的同時輸出24bits(3字節)的消息(out_bytes[23:16]為第一字節,out_bytes[15:8]為第二字節,以此類推)。
當發出接收完成信號done時,out_bytes必須是有效的,其他時候可以輸出任何的內容(即不在乎輸出什么。)
小提示:使用前一題Problem 134 PS/2 packet parser / Fsm ps2 中的狀態機,并添加用于捕捉輸入字節的數據路徑即可。

圖片來自HDLBits
模塊端口聲明
moduletop_module( inputclk, input[7:0]in, inputreset,//Synchronousreset output[23:0]out_bytes, outputdone);
題目解析
本題在前一題的三個沒有輸出動作的狀態上添加out_bytes等于輸入即可完成。值得注意的是狀態4可以跳轉為狀態2,所以狀態4也需要對out_bytes賦值。
moduletop_module(
inputlogicclk,
inputlogic[7:0]in,
inputlogicreset,//Synchronousreset
output[23:0]out_bytes,
outputlogicdone);
typedefenumlogic[1:0]{S0=2'd0,S1=2'd1,S2=2'd2,Done=2'd3}state_def;
state_defcur_state,next_state;
//Statetransitionlogic(combinational)
always_combbegin
case(cur_state)
S0:begin
next_state=S1;
end
S1:begin
next_state=S2;
end
S2:begin
next_state=in[3]?S0:Done;
end
Done:begin
next_state=in[3]?S0:Done;
end
default:begin
next_state=Done;
end
endcase
end
//Stateflip-flops(sequential)
always_ff@(posedgeclk)begin
if(reset)begin
cur_state<=?Done?;
????????end
????????else?begin
????????????cur_state?<=?next_state?;
????????end
????????
????end
????//?Output?logic
????assign?done?=?(cur_state?==?S2)?;
????assign?out_bytes?=?done???out_bytes_temp?:?24'd24?;
????var?logic?[23:0]?out_bytes_temp?;
????always_ff?@(?posedge?clk?)?begin?
????????if?(next_state?==?S0)?begin
????????????out_bytes_temp[23:16]?<=?in?;?
????????end
????????else?if?(next_state?==?S1)?begin
????????????out_bytes_temp[15:8]??<=?in?;
????????end
????????else?if?(next_state?==?S2)?begin
????????????out_bytes_temp[7:0]???<=?in?;
????????end
????????
????end
endmodule

點擊Submit,等待一會就能看到下圖結果:

注意圖中無波形。
這一題就結束了。
總結
今天的幾道題就結束了,對于狀態機的理解還是有益處的,三段式狀態機是題目一直推崇的,類似狀態機的公示,可以“套”進去。
審核編輯:劉清
-
HDL
+關注
關注
8文章
332瀏覽量
48973 -
狀態機
+關注
關注
2文章
499瀏覽量
29141 -
fsm
+關注
關注
0文章
36瀏覽量
13112 -
Verilog語言
+關注
關注
0文章
113瀏覽量
8790
原文標題:HDLBits: 在線學習 SystemVerilog(十九)-Problem 126-133(狀態機二)
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
Verilog狀態機+設計實例
如何寫好狀態機
什么是狀態機 狀態機的描述三種方法
淺談狀態機的要素、分類
什么是狀態機?狀態機5要素
狀態模式(狀態機)
如何合理高效地使用狀態機呢?
評論