---
# System prepended metadata

title: 狀態機的一些小小的coding style
tags: [verilog]

---

# 狀態機的一些小小的coding style

###### tags: `verilog`

之前在網路上看到一些實例
狀態機基本上分為三個區塊(我比較喜歡這樣寫)

第一個always 用來做時序的控制
一個rising edge 來就做狀態的轉變
將目前的state 轉成next_state

第二個always 用來推算出目前這個state
所對應到的下一個next stage是什麼stage

第三個always 專門用來處理在目前這個state
所要得到的輸出是什麼

e.g code (之前的serial)

```=verilog
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output reg done
); 

	reg [3:0]state,nextstate;
	
	always@(posedge clk) //第一個always
	begin
		if (reset) state<=1'd0;
			else state<=nextstate;
	end
	
	always@(*) //第二個always
	begin
		case(state)
		4'd0: 
			if (in) nextstate<=4'd0;
			else nextstate<=4'd1;
		4'd1:
			nextstate<=4'd2;
		4'd2:
			nextstate<=4'd3;
		4'd3:
			nextstate<=4'd4;
		4'd4:
			nextstate<=4'd5;
		4'd5:
			nextstate<=4'd6;
		4'd6:
			nextstate<=4'd7;
		4'd7:
			nextstate<=4'd8;
		4'd8:
			nextstate<=4'd9;
		4'd9:
			if (in) nextstate<=4'd10;
			else nextstate<=4'd11;
		4'd10: 
			if (in) nextstate<=4'd0;
			else nextstate<=4'd1;
		4'd11:
			if (in) nextstate<=4'd0;
			else nextstate<=4'd11;
		default:nextstate<=4'd0;
		endcase
	end
	
	always@(*)//第三個always
	begin
		case (state)
		4'd10: done<=1'd1;
		default: done<=1'd0; 
		endcase
	end
	
endmodule

```

有一些東西需要改善
比較好的coding style


1. parameter 把每個state都透過parameter去做處理
可以直接用state的變數名進行使用 (比較直觀 好debug)
例如在第二個always的時候 case裡面可以直接用變數名
只用數字之後會不好debug

2. 在第三個always裡面 用nextstate對輸出進行控制
因為state的改變是check clock是否有rising edge
所以在這邊 case裡面以state來決定輸出不太好
因為不知道現在的這個stage 是clk來之前的舊state
還是已經更新的新的state
沒有考慮到延遲的情況之下 也就是理想的狀況
這裡的state是舊的state 沒有更新的state
但是考慮到真實的電路設計 這裡還是用next_state判斷輸出會比較好
因為next_state不用考慮到clk是否已經更新到值 (已經用組合邏輯算好了)

3. 多一個state就是多一個ff
所以可以少用到state就可以少用到硬體資源
這邊的data 8bit循序存取我是用8個state去做
基本上可以合併成一個state 裡面用counter去做狀態的改變
(數8 0~8變化8次 8個rising edge 數到8就進去下個state)
然後counter也不用想的太複雜 考慮到很多的state counter的功能也不一樣
(要歸0 +1 原值等等)
這邊就將counter的輸出用一個多工器去做 sel用state去選就對了
總之我就繼續來寫寫看 來做一個比較好的版本 (serial)