還記得之前軟件的同事說過的一句話。怎么凸顯自己的工作量,就是自己給自己寫BUG。
看過夏宇聞老師書的都知道,verilog的FSM有moore和mealy,然后有一段,二段,三段式。記得我還是學生的時候,看到這里的時候,感覺很燒腦。畢竟這與數字電路設計息息相關。
今天我想把問題簡單化。只談mealy型三段式寫法。
借用前輩們總結的一句話說:三段式描述方法雖然代碼結構復雜了一些,但是換來的優勢是使 FSM 做到了同步寄存器輸出,消除了組合邏輯輸出的不穩定與毛刺的隱患,而且更利于時序路徑分組,一般來說在 FPGA/CPLD 等可編程邏輯器件上的綜合與布局布線效果更佳。
?(閃耀著哲學的光輝......)
//3-paragraph method to describe FSM
//Describe sequential state transition in the 1st sequential always block
//State transition conditions in the 2nd combinational always block
//Describe the FSM out in the 3rd sequential always block
//Verilog Training -- How to write FSM bettermodule state3 ( rst_n,clk,i1,i2,o1,o2,err);input rst_n,clk;
input i1,i2;
output o1,o2,err;
reg o1,o2,err;reg [2:0] NS,CS;//one hot with zero idle
parameter [2:0] IDLE = 3'b000;
parameter [2:0] S1 = 3'b001;
parameter [2:0] S2 = 3'b010;
parameter [2:0] ERROR = 3'b100;//1st always block, sequential state transition
always @(posedge clk or negedge rst_n)if (!rst_n) CS <= IDLE; else CS <=NS; //2nd always block, combinational condition judgment
always @ (rst_n or CS or i1 or i2)beginNS = 3'bx;case (CS)IDLE: beginif (~i1) NS = IDLE;if (i1 && i2) NS = S1;if (i1 && ~i2) NS = ERROR;endS1: beginif (~i2) NS = S1;if (i2 && i1) NS = S2;if (i2 && (~i1)) NS = ERROR;endS2: beginif (i2) NS = S2;if (~i2 && i1) NS = IDLE;if (~i2 && (~i1)) NS = ERROR;endERROR: beginif (i1) NS = ERROR;if (~i1) NS = IDLE;endendcaseend//3rd always block, the sequential FSM output
always @ (posedge clk or negedge rst_n)if (!rst_n){o1,o2,err} <= 3'b000;elsebegin{o1,o2,err} <= 3'b000;case (NS)IDLE: {o1,o2,err}<=3'b000;S1: {o1,o2,err}<=3'b100;S2: {o1,o2,err}<=3'b010;ERROR: {o1,o2,err}<=3'b111;endcaseendendmodule
同樣這段代碼也很好理解:
module FSM(clk,clr,out,start,step2,step3);
input clk;
input clr;
input start;
input step2;
input step3;output[2:0] out;reg[2:0] out;
reg[1:0] state,next_state;/*狀態編碼,采用格雷(Gray)編碼方式*/
parameter state0 = 2'b00;
parameter state1 = 2'b01;
parameter state2 = 2'b11;
parameter state3 = 2'b10; /*該進程定義起始狀態*/
always @(posedge clk or posedge clr)
begin if (clr) state <= state0; else state <= next_state;
end/*該進程實現狀態的轉換*/
always @(state or start or step2 or step3)
begin case (state)state0: beginif (start) next_state <=state1;else next_state <=state0;endstate1: beginnext_state <= state2;endstate2: beginif (step2) next_state <=state3;else next_state <=state0;endstate3: beginif (step3) next_state <=state0;else next_state <=state3;enddefault: next_state <=state0; /*default語句*/endcase
end/*該進程定義組合邏輯(FSM的輸出)*/
always @(state)
begincase(state)state0: out=3'b001;state1: out=3'b010;state2: out=3'b100;state3: out=3'b111;default:out=3'b001; /*default語句,避免鎖存器的產生*/endcase
endendmodule
狀態轉移圖如下:
總結
文章難免會有些水平不足,不正確的地方請大家多多指正,共同進步。
?