# Fsm serialdata ###### tags: `HDLBits` main_code ```=V /* Filename : top_module.v Simulator : Quartus II 20.1 ModelSim 2020.1 scription : serial communications protocols Release : Aug.17,2021 */ module top_module( input clk, input reset, input in, output reg [7:0] out_byte, output reg done); //parameter parameter idle=3'd0, start=3'd1, data=3'd2, stop=3'd3, error=3'd4; //fsm ////regs reg [2:0]state,nextstate; reg [3:0]count; ////state transition always@(posedge clk) begin if (reset) state<=1'd0; else state <=nextstate; end ////next_state logic always@(*) begin case (state) idle: if (in) nextstate=idle; else nextstate=start; start: nextstate=data; data: if (count!=4'd7) nextstate=data; else if (in) nextstate=stop; else nextstate=error; stop:if (in) nextstate=idle; else nextstate=start; error:if (in) nextstate=idle; else nextstate=error; default:nextstate=idle; endcase end ////state output logic always@(*) begin case(state) stop:done<=1'd1; default:done<=1'd0; endcase end //data output always@(posedge clk) begin if (reset) out_byte<=8'd0; else if ((state==start || state==data) && count<7) begin //count 0~6 out_byte[7]<=in; out_byte[6]<=out_byte[7]; out_byte[5]<=out_byte[6]; out_byte[4]<=out_byte[5]; out_byte[3]<=out_byte[4]; out_byte[2]<=out_byte[3]; out_byte[1]<=out_byte[2]; out_byte[0]<=out_byte[1]; end else out_byte<=out_byte; end //cnt always@(posedge clk) begin case (state) data:begin if (count==3'd7) count<=count; else count<=count+4'd1; end default:count<=4'd0; endcase end endmodule ``` testbench_1 ```=V /* Filename : top_module_test.v Simulator : Quartus II 20.1 ModelSim 2020.1 scription : serial communications protocols testing ckt (stop state) Release : Aug.17,2021 */ //設定timescale `timescale 1ns/100ps //設定testbench名 module top_module_test; //input用reg output用wire reg reset,clk,in; wire done; wire [7:0]out_byte; //引用待測模組 top_module t1(.reset(reset), .clk(clk), .in(in), .done(done), .out_byte(out_byte)); //clk signal initial #0 clk=1'b1; always #5 clk =~clk; //rst input initial begin: in_set_blk #0 in =1'b1; reset=1'b1; #12 reset=1'b0; #10 in =~in; #10 in =~in; #5 in =~in; #5 in =~in; #25 in =~in; #15 in =~in; #20 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #10 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; end //signals initial begin: signals_blks integer i; for (i=0;i<200;i=i+1) begin #1 $display (" time=",$time, " in=%d out_byte=%h count=%d done=%d \n",in,out_byte,t1.count,done); $display (" time=",$time, " state=%d nextstate=%d\n",t1.state,t1.nextstate); end #10 $stop; #10 $finish; end endmodule ``` testbench_2 ``` /* Filename : top_module_test2.v Simulator : Quartus II 20.1 ModelSim 2020.1 scription : serial communications protocols testing ckt (error state) Release : Aug.17,2021 */ //設定timescale `timescale 1ns/100ps //設定testbench名 module top_module_test2; //input用reg output用wire reg reset,clk,in; wire done; wire [7:0]out_byte; //引用待測模組 top_module t1(.reset(reset), .clk(clk), .in(in), .done(done), .out_byte(out_byte)); //clk signal initial #0 clk=1'b1; always #5 clk =~clk; //rst input initial begin: in_set_blk #0 in =1'b1; reset=1'b1; #12 reset=1'b0; #10 in =~in; #10 in =~in; #5 in =~in; #5 in =~in; #25 in =~in; #15 in =~in; #20 in =~in; #5 in =~in; #5 in =~in; #15 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; #5 in =~in; end //signals initial begin: signals_blks integer i; for (i=0;i<200;i=i+1) begin #1 $display (" time=",$time, " in=%d out_byte=%h count=%d done=%d \n",in,out_byte,t1.count,done); $display (" time=",$time, " state=%d nextstate=%d\n",t1.state,t1.nextstate); end #10 $stop; #10 $finish; end endmodule ``` 終於完工了QQ 一直修bug 先看電路圖來得出狀態圖 再用狀態圖去實現電路 注意資料在哪些rising edge去取得 就是counter要跟狀態配合好 (在這邊花了很多時間) 電路功能說明 一開始reset 狀態會從idle開始 狀態的改變都是在rising edge發生 當in為1 仍持續在idle狀態 當in為0 進入到start狀態 在下一個clk rising edge 進入到data狀態 注意 題目的需求就是 在 Start狀態進到data狀態的這個rising edge 就開始要存第一個data值(data的LSB) 所以這邊的counter 還有 state 要配合好 不然會出錯 由Start狀態進到data狀態的這個rising edge開始為第一個data 共要取8個data 也就是需要8個rising edge 最後這邊也是要注意 從data state 進入到其他的state (可能是stop 也可能是error state) 這個rising edge 是不對data進行存值的 (在這裡發生了很多錯誤) 在data state 進入到其他的state的這個rising edge 當in為0 則進到error state(錯誤) in為1 進到stop state(完成) 然後再看下一個in是0是1 分別進到下一個狀態(等等看state graph就知道) state graph ![](https://i.imgur.com/k0wLQgl.jpg) modelsim ![](https://i.imgur.com/mbK3Jyn.jpg) ![](https://i.imgur.com/gNL37Nb.jpg)