HBLbits_Verilog Basic_Fsm serial
In many (older) serial communications protocols, each data byte is sent along with a start bit and a stop bit, to help the receiver delimit bytes from the stream of bits. One common scheme is to use one start bit (0), 8 data bits, and 1 stop bit (1). The line is also at logic 1 when nothing is being transmitted (idle).
Design a finite state machine that will identify when bytes have been correctly received when given a stream of bits. It needs to identify the start bit, wait for all 8 data bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.
Some timing diagrams
在許多(較舊的)串列通信協定中,每個資料位元組都與起始位元和停止位一起發送,以幫助接收器從位元流中分隔位元組。 一種常見的方案是使用一個起始位(0),8個資料位元和1個停止位(1)。 當沒有任何傳輸(空閒)時,線路也處於邏輯1。
狀態轉移圖
根據描述,我們設計一個狀態轉移圖:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
parameter stop = 0,b0=1,b1=2,b2=3,b3=4,b4=5, b5=6,b6=7,b7=8,stop_ok=9,stop_notok=10,start = 11;
//parameter idle = 0,start = 1,b0=2,b1=3,b2,=4,b3,b4,b5,b6,b7,stop;
reg [4:0]state ,next;
always @(*)
begin
case(state)
stop:next = (~in)? start:stop;
start: next = b0;
b0: next =b1;
b1: next = b2;
b2: next = b3;
b3: next = b4;
b4: next = b5;
b5: next = b6;
b6: next = b7;
b7: next = in?stop_ok:stop_notok;
//stop: next = in?stop_ok: idle;
stop_ok: next = (~in)?start:stop;
stop_notok: next = in?stop:stop_notok;
endcase
end
always @(posedge clk)
begin
if (reset)
state <= stop;
else
state <= next;
end
assign done =(state ==stop_ok);
endmodule
要注意的是最後一步的設計,也就是STOP狀態之後的判斷,如果輸入資料為1,則資料接受結束,給出接受完畢信號done;否則的話,我們不得不等到結束位元標誌1之後才能進入下一串資料的接收,且一旦進入這種情況,則拋棄這一串資料的接受,也即不會產生接受完畢信號done。
最後不得不說的是,Uart接受協議可以有多個結束位元,甚至還可以有校驗位等,一旦確認了協議,我們就可以編寫類似的代碼來實現資料的接收。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
parameter stop = 0,b0=1,b1=2,b2=3,b3=4,b4=5,b5=6,b6=7,b7=8,stop_ok=9,stop_notok=10,start = 11;
//parameter idle = 0,start = 1,b0=2,b1=3,b2,=4,b3,b4,b5,b6,b7,stop;
reg [4:0]state ,next;
always @(*)
begin
case(state)
stop:next = (~in)? start:stop;
start: next = b0;
b0: next =b1;
b1: next = b2;
b2: next = b3;
b3: next = b4;
b4: next = b5;
b5: next = b6;
b6: next = b7;
b7: next = in?stop_ok:stop_notok;
//stop: next = in?stop_ok: idle;
stop_ok: next = (~in)?start:stop;
stop_notok: next = in?stop:stop_notok;
endcase
end
always @(posedge clk)
begin
if (reset)
state <= stop;
else
state <= next;
end
assign done =(state ==stop_ok);
endmodule
很多串列通信協定發送過程中會在資料位元組前後增加標記來標識位元組首尾,即包含 start 位和 stop 位元,比如 UART 協議就是這樣。該題就類比了這種類型協議的接收端行為。這裡開始的標記是低電平,結束的標記是高電平,在開始和結束之間傳輸的 bit 位元為8即一個位元組,這是正確接收的條件,當滿足該條件後會在 stop 位元後面的時鐘沿給出 done 的輸出標記。如果不滿足該條件,比如起始 start 條件不滿足,則會一直等待知道接收到低電平信號才開始;又如 start 開始後,中間的位數超過了8 bit,即8 bit 後一直是低電平信號,不出現高電平的 stop 信號,則 receiver 繼續等待知道出現高電平位才結束,但這是一個錯誤接收,不會給出 done 的輸出標記。波形圖如下所示。
沒有留言:
張貼留言