HDLBits答案(19)_Verilog有限状态机(6)
Verilog有限狀態機(6)
HDLBits鏈接
前言
今天繼續更新狀態機小節的習題。
題庫
Fsm hdlc
同步幀檢測涉及對數據的連續位流進行解碼,以尋找指示幀(數據包)開始和結束的位模式。 6個連續的1(即01111110)是表示幀邊界的“標志”。 為了避免數據流意外包含“標志”,發送方必須在接收方必須檢測并丟棄的每5個連續的1秒后插入一個零。 如果連續7個或更多1,我們還需要發出錯誤信號。
可以通過狀態機來識別下面三種序列:
0111110:表示5個1后面的0bit需被忽略;
01111110:表示一幀的開始或結束;
01111111…:錯誤
當狀態機被復位時,它應當表現為之前的輸入為0;
下面是三種波形示例:
官方提供的狀態機設計提示:
Solution:
//----------------way1---------------------- module top_module(input clk,input reset, // Synchronous resetinput in,output disc,output flag,output err);parameter NONE = 4'd0,ONE = 4'd1,TWO = 4'd2;parameter THREE = 4'd3,FOUR = 4'd4,FIVE = 4'd5;parameter SIX = 4'd6,ERROR = 4'd7;parameter DISC = 4'd8,FLAG = 4'd9;reg [3:0] current_state,next_state;always @(*) begincase(current_state)NONE:beginnext_state = in ? ONE : NONE;endONE:beginnext_state = in ? TWO : NONE;endTWO:beginnext_state = in ? THREE : NONE;endTHREE:beginnext_state = in ? FOUR : NONE;endFOUR:beginnext_state = in ? FIVE : NONE;endFIVE:beginnext_state = in ? SIX : DISC;endSIX:beginnext_state = in ? ERROR : FLAG;endDISC:beginnext_state = in ? ONE : NONE;endFLAG:beginnext_state = in ? ONE : NONE;endERROR:beginnext_state = in ? ERROR : NONE;endendcaseendalways @(posedge clk) beginif(reset)begincurrent_state <= NONE;endelse begincurrent_state <= next_state;endendalways @(posedge clk) beginif(reset)begindisc <= 1'd0;flag <= 1'd0;err <= 1'd0;endelse begincase(next_state)DISC:begindisc <= 1'd1;flag <= 1'd0;err <= 1'd0;endFLAG:begindisc <= 1'd0;flag <= 1'd1;err <= 1'd0;endERROR:begindisc <= 1'd0;flag <= 1'd0;err <= 1'd1;enddefault:begindisc <= 1'd0;flag <= 1'd0;err <= 1'd0;endendcaseendendendmodule //----------------way2---------------------- module top_module(input clk,input reset, // Synchronous resetinput in,output disc,output flag,output err);parameter NONE = 3'd0,DATA = 3'd1;parameter DISC = 3'd2,FLAG = 3'd3,ERROR = 3'd4;reg [2:0] current_state,next_state;reg [2:0] counter;always @(*) begincase(current_state)NONE:beginnext_state = in ? DATA : NONE;endDATA:begincase(counter)3'd5: next_state = in ? DATA : DISC;3'd6: next_state = in ? ERROR : FLAG;default:next_state = in ? DATA : NONE;endcaseendDISC:beginnext_state = in ? DATA : NONE;endFLAG:beginnext_state = in ? DATA : NONE;endERROR:beginnext_state = in ? ERROR : NONE;endendcaseendalways @(posedge clk) beginif(reset)begincurrent_state <= NONE;endelse begincurrent_state <= next_state;endendalways @(posedge clk) beginif(reset)begindisc <= 1'd0;flag <= 1'd0;err <= 1'd0;counter <= 3'd0;endelse begincase(next_state)DATA:begindisc <= 1'd0;flag <= 1'd0;err <= 1'd0;counter <= counter + 1'd1;endDISC:begindisc <= 1'd1;flag <= 1'd0;err <= 1'd0;counter <= 3'd0;endFLAG:begindisc <= 1'd0;flag <= 1'd1;err <= 1'd0;counter <= 3'd0;endERROR:begindisc <= 1'd0;flag <= 1'd0;err <= 1'd1;counter <= 3'd0;enddefault:begindisc <= 1'd0;flag <= 1'd0;err <= 1'd0;counter <= 3'd0;endendcaseendendendmodule其中way1與題目提示的思路相同,其中第三段狀態機一開始忘記加reset的那種情況,果然還是長時間沒接觸verilog手生了,以后繼續練習;
way2使用counter去掉中間狀態,靠輸入和counter的值來決定狀態轉移,是一種米利狀態機的思想;狀態轉移圖如下(手繪有點丑,見諒):
米利型狀態機
檢測輸入的X中”101“是否出現,出現的話輸出Z為1,否則為0。復位為異步低電平復位;只允許出現3種狀態;允許交疊檢測:即輸入若為10101時,Z應該在時刻3和時刻5各輸出一次1;
代碼中主要妙在兩處:一是如何用3種狀態表示,需在第三種狀態中將輸出與輸入關聯起來;二是如何進行交疊檢測,狀態的轉移有妙處;
Solution:
module top_module (input clk,input aresetn, // Asynchronous active-low resetinput x,output z ); parameter S0 = 2'd0,S1 = 2'd1,S2 = 2'd2;reg [1:0] current_state,next_state;always @(*) begincase(current_state)S0: next_state = x ? S1 : S0;S1: next_state = x ? S1 : S2;S2: next_state = x ? S1 : S0;endcaseendalways @(posedge clk or negedge aresetn) beginif(~aresetn)begincurrent_state <= S0;endelse begincurrent_state <= next_state;endendalways @(*) beginz = (current_state == S2) ? x : 1'b0;endendmoduleQ5a:Serial two’s complementer(Moore FSM)
作者這里假設我們這邊輸入的都是負數,不用管符號位的問題;即補碼全部都是取反加1求得。
以上圖為例,輸入的左邊為低位數據,右邊為高位數據;即輸入為00110100,則取反加1后得輸出為11001100;
取反操作好進行,主要麻煩在加一的操作上,不知道進位到哪一位為止,此時我們用狀態機來解決;若最前面的輸入都是0的話,取反均為1,低位加1的時候一直進位,則輸出都是0,直到輸入有個1為止(取反加1不進位),這一階段我們用一個狀態S0來表示;后面階段就將輸入取反進行輸出即可,因為進位鏈在S0狀態已結束;
因為是摩爾型狀態機,狀態的轉移與輸入無關,所以我們這里用到3個狀態,代碼如下所示:
Solution:
module top_module (input clk,input areset,input x,output z ); parameter S0 = 2'd0, S1 = 2'd1, S2 = 2'd2;reg [1:0] current_state, next_state;always @(*) begincase(current_state)S0: next_state = x ? S1 : S0;S1: next_state = x ? S2 : S1;S2: next_state = x ? S2 : S1;endcaseendalways @(posedge clk or posedge areset) beginif(areset)begincurrent_state <= S0;endelse begincurrent_state <= next_state;endendassign z = (current_state == S1);endmoduleQ5b:Serial two’s complementer(Mealy FSM)
題意與上題相同,此時用米利型狀態機實現。下面是官方提供的狀態轉移提示:
module top_module (input clk,input areset,input x,output z ); parameter S0 = 1'b0, S1 = 1'b1;reg current_state,next_state;always @(*) begincase(current_state)S0: next_state = x ? S1 : S0;S1: next_state = S1;endcaseendalways @(posedge clk or posedge areset) beginif(areset)begincurrent_state <= S0;endelse begincurrent_state <= next_state;endendassign z = ((current_state == S0) && x) || ((current_state == S1) && ~x);endmodule結語
今天先更新這幾題吧,大家如果對轉補碼的題目還有什么疑問歡迎評論交流,代碼有不足之處還望指正。
總結
以上是生活随笔為你收集整理的HDLBits答案(19)_Verilog有限状态机(6)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: HDLBits答案(18)_Verilo
 - 下一篇: HDLBits答案(20)_Verilo