HDLBits答案(19)_Verilog有限状态机(6)
Verilog有限狀態(tài)機(6)
HDLBits鏈接
前言
今天繼續(xù)更新狀態(tài)機小節(jié)的習題。
題庫
Fsm hdlc
同步幀檢測涉及對數(shù)據(jù)的連續(xù)位流進行解碼,以尋找指示幀(數(shù)據(jù)包)開始和結束的位模式。 6個連續(xù)的1(即01111110)是表示幀邊界的“標志”。 為了避免數(shù)據(jù)流意外包含“標志”,發(fā)送方必須在接收方必須檢測并丟棄的每5個連續(xù)的1秒后插入一個零。 如果連續(xù)7個或更多1,我們還需要發(fā)出錯誤信號。
可以通過狀態(tài)機來識別下面三種序列:
0111110:表示5個1后面的0bit需被忽略;
01111110:表示一幀的開始或結束;
01111111…:錯誤
當狀態(tài)機被復位時,它應當表現(xiàn)為之前的輸入為0;
下面是三種波形示例:
官方提供的狀態(tài)機設計提示:
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與題目提示的思路相同,其中第三段狀態(tài)機一開始忘記加reset的那種情況,果然還是長時間沒接觸verilog手生了,以后繼續(xù)練習;
way2使用counter去掉中間狀態(tài),靠輸入和counter的值來決定狀態(tài)轉移,是一種米利狀態(tài)機的思想;狀態(tài)轉移圖如下(手繪有點丑,見諒):
米利型狀態(tài)機
檢測輸入的X中”101“是否出現(xiàn),出現(xiàn)的話輸出Z為1,否則為0。復位為異步低電平復位;只允許出現(xiàn)3種狀態(tài);允許交疊檢測:即輸入若為10101時,Z應該在時刻3和時刻5各輸出一次1;
代碼中主要妙在兩處:一是如何用3種狀態(tài)表示,需在第三種狀態(tài)中將輸出與輸入關聯(lián)起來;二是如何進行交疊檢測,狀態(tài)的轉移有妙處;
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)
作者這里假設我們這邊輸入的都是負數(shù),不用管符號位的問題;即補碼全部都是取反加1求得。
以上圖為例,輸入的左邊為低位數(shù)據(jù),右邊為高位數(shù)據(jù);即輸入為00110100,則取反加1后得輸出為11001100;
取反操作好進行,主要麻煩在加一的操作上,不知道進位到哪一位為止,此時我們用狀態(tài)機來解決;若最前面的輸入都是0的話,取反均為1,低位加1的時候一直進位,則輸出都是0,直到輸入有個1為止(取反加1不進位),這一階段我們用一個狀態(tài)S0來表示;后面階段就將輸入取反進行輸出即可,因為進位鏈在S0狀態(tài)已結束;
因為是摩爾型狀態(tài)機,狀態(tài)的轉移與輸入無關,所以我們這里用到3個狀態(tài),代碼如下所示:
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)
題意與上題相同,此時用米利型狀態(tài)機實現(xiàn)。下面是官方提供的狀態(tài)轉移提示:
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