www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > > FPGA開源工作室

Verilog實現(xiàn)狀態(tài)機與狀態(tài)機經(jīng)典示例

1.狀態(tài)機原理與三段式狀態(tài)機

MOORE 與 MEALEY 狀態(tài)機的特征?

Moore 狀態(tài)機的輸出僅與當前狀態(tài)值有關(guān), 且只在時鐘邊沿到來時才會有狀態(tài)變化。次態(tài)=f(現(xiàn)狀,輸入),輸出=f(現(xiàn)狀)

Mealy 狀態(tài)機的輸出不僅與當前狀態(tài)值有關(guān), 而且與當前輸入值有關(guān)。次態(tài)=f(現(xiàn)狀,輸入),輸出=f(現(xiàn)狀,輸入)

描述同一個事務(wù),mealy的狀態(tài)更少。

通用mealy三段式狀態(tài)機(建議實際工程中采用的結(jié)構(gòu))


//------采用獨熱碼或格雷碼或其他方式編碼狀態(tài)parameter IDLE = ...parameter S0 = ......reg [x:0] curr_state;reg [x:0] next_state; //------每個時鐘只產(chǎn)生一次狀態(tài)變化always @(posedge clk or  posedge asy_rst)begin if(asy_rst)    curr_state <= IDLE ; else curr_state <= next_state; end //------產(chǎn)生的下一狀態(tài)的組合邏輯always @(*)begin next_state = 'bx; case(curr_state) IDLE: if(輸入) next_state = S0 ;else...; S0: if(輸入) next_state = ...; ... default:       next_state = ...; endcaseend/************************時序或組合二選一***********************///------時序邏輯輸出(比組合邏輯延時一個時鐘)always@(posedge clk or posedge asy_rst)begin if(asy_rst)out<= ...; else case(curr_state) sO: if(...) out <= ...; sO: if(...) out <= ...; default: out <= ...; endcaseend//------組合邏輯輸出 采用 assign 或alwaysalways @(*)begin if(asy_rst)out = ...; else case(curr_state) sO: if(...) out  = ...; sO: if(...) out  = ...; default: out  = ...; endcaseend/***********************************************************/

2.狀態(tài)機示例

2.1自動飲料售賣機/賣報機

題目:商品是5分錢,只能投3種硬幣:1分,2分,5分,考慮找零。

思路1:采用狀態(tài)機,共分為5個狀態(tài),S0-S4代表已經(jīng)投入的錢,畫出狀態(tài)轉(zhuǎn)換圖(略),采用三段式mealy狀態(tài)機。

思路2:(更簡單)不采用狀態(tài)機,直接對輸入的錢進行加法運算,多余5分就輸出和找零,同時將內(nèi)部加法器清零。

另一個版本:用Verilog實現(xiàn)接受0.5元,1元的可樂售賣機,單價2.5元,考慮找零和出貨。


module auto_sell_better#(parameter I_WD = 4 , O_WD = 4)(input clk,input asy_rst,input [I_WD-1:0] i_dat,input i_val, output reg [O_WD-1:0] o_money,//找零output reg o_goods          //商品 ); parameter S0=4'b0000; parameter S1=4'b0001; //1分錢parameter S2=4'b0010; parameter S3=4'b0100; parameter S4=4'b1000; //4分錢reg [3:0] curr_s;reg [3:0] next_s;//每個時鐘只產(chǎn)生一次狀態(tài)變化always @(posedge clk or  posedge asy_rst)begin if(asy_rst) curr_s <= S0; else curr_s <= next_s; end//產(chǎn)生的下一狀態(tài)的組合邏輯always @(*)beginnext_s = 'dx;case(curr_s) S0: if(i_dat == 1)          next_s = S1;  else if(i_dat == 2)     next_s = S2; else if(i_dat == 5)     next_s = S0; else next_s = S0; S1: if(i_dat == 1)          next_s = S2;  else if(i_dat == 2)     next_s = S3;  else if(i_dat == 5)     next_s = S0;  else next_s = S1; S2: if(i_dat == 1)          next_s = S3;  else if(i_dat == 2)     next_s = S4;  else if(i_dat == 5)     next_s = S0;  else next_s = S2;  S3: if(i_dat == 1)          next_s = S4;  else if(i_dat == 2)     next_s = S0;  else if(i_dat == 5)     next_s = S0;  else next_s = S3;  S4: if(i_dat == 1)          next_s = S0;  else if(i_dat == 2)     next_s = S0;  else if(i_dat == 5)     next_s = S0;  else next_s = S4;  default:    next_s = S0;endcaseend/**************************時序邏輯的輸出*******************************/always @(posedge clk or  posedge asy_rst)begin if(asy_rst) begin o_money <= 0; o_goods <= 0; end  else case(curr_s) S0: begin o_money <= 0;  if(i_dat==5) o_goods <= 1;  else o_goods <= 0;  end S1:  begin  if(i_dat==5) begin o_money <= 1; o_goods <= 1; end else begin o_money <= 0; o_goods <= 0; end end S2:  begin  if(i_dat==5) begin o_money <= 2; o_goods <= 1; end else begin o_money <= 0; o_goods <= 0; end end S3:  begin  if(i_dat==5) begin o_money <= 3; o_goods <= 1; end else if (i_dat==2) begin o_money <= 0; o_goods <= 1; end else begin o_money <= 0; o_goods <= 0; end  end S4:  begin  if(i_dat==5) begin o_money <= 4; o_goods <= 1; end else if (i_dat==2) begin o_money <= 1; o_goods <= 1; end else if (i_dat==1) begin o_money <= 0; o_goods <= 1; end  end default : begin o_money <= 0; o_goods <= 0;end endcaseend  /***************************不采用狀態(tài)機的方法**********************************/reg [3:0] add_in;//內(nèi)部計算輸入的錢的和reg [3:0] a_money;//找零reg a_goods;//商品always @(posedge clk or  posedge asy_rst)begin if(asy_rst) begin add_in <= 0; a_money <= 0; a_goods <= 0; end else if(i_val) begin if(add_in+i_dat >=5) begin add_in <= 0;//清零 a_money <= add_in + i_dat - 5;//找零 a_goods <= 1;//輸出 end else begin add_in <= add_in + i_dat; a_money <= 0; a_goods <= 0;  end end else begin add_in <= 0; a_money <= 0; a_goods <= 0; endendendmodule
/////////////////////////////////////testbench//////////////////////////////////module auto_sell_sim;parameter CLK_PERIOD = 10; //仿真周期10ns=100Mparameter RST_CYCLE = 5; //復(fù)位周期數(shù)parameter RST_TIME = RST_CYCLE * CLK_PERIOD;  reg sim_clk;reg sim_asy_rst; initialbegin sim_clk = 0; sim_asy_rst = 1; #RST_TIME sim_asy_rst = 0;end always #(CLK_PERIOD/2) sim_clk = ~sim_clk;/******************************************************/parameter I_WD = 4;parameter O_WD = 4;reg [I_WD-1:0]sim_dat;reg [I_WD-1:0]sim_i_dat;reg sim_i_val;always@(posedge sim_clk or posedge sim_asy_rst)begin if(sim_asy_rst) begin sim_i_dat <= 0;  sim_i_val <= 0; end else begin sim_dat <= {$random}%6;//產(chǎn)生0-5的隨機數(shù) if( sim_dat== 1 || sim_dat ==2 || sim_dat==5) begin sim_i_dat <= sim_dat;  sim_i_val <= 1; end else begin sim_i_dat <= 0;  sim_i_val <= 1; end endend wire [O_WD-1:0] o_money;wire o_goods;auto_sell_better auto_sell_better_u( //auto_sell auto_sell_u (.clk( sim_clk ),.asy_rst( sim_asy_rst ),.i_dat( sim_i_dat ),.i_val( sim_i_val),.o_money(o_money),.o_goods(o_goods) );

2.2序列檢測器

筆試題目:如果序列長度為8,需要8個狀態(tài),最少(3)個寄存器進行狀態(tài)轉(zhuǎn)換(mealy)。

題目:用狀態(tài)機實現(xiàn) 101101 的序列檢測。

思路:

畫出mealy狀態(tài)轉(zhuǎn)換圖,并進行化簡[1],灰色表示合并為一個:


“101101”序列檢測狀態(tài)機輸出表

果采用moore狀態(tài)機,其狀態(tài)就多了,且輸出比mealy延時一個時鐘參考[1]:

//mealy狀態(tài)機module seq_detect#(parameter I_WD = 1 , O_WD = 1)(input clk,input asy_rst,input [I_WD-1:0] i_dat,input i_val,output reg [O_WD-1:0] o_detect  ); parameter S0=6'b000001; parameter S1=6'b000010; parameter S2=6'b000100; parameter S3=6'b001000; parameter S4=6'b010000; parameter S5=6'b100000;  //101101reg [5:0] curr_s;reg [5:0] next_s;//每個時鐘只產(chǎn)生一次狀態(tài)變化always @(posedge clk or  posedge asy_rst)begin if(asy_rst) curr_s <= S0; else curr_s <= next_s; end //產(chǎn)生的下一狀態(tài)的組合邏輯always @(*)beginnext_s = 'dx;case(curr_s) S0: if(i_dat == 1)          next_s = S1;  else next_s = S0; S1: if(i_dat == 0)          next_s = S2;  else next_s = S1; S2: if(i_dat == 1)          next_s = S3;  else next_s = S0;  S3: if(i_dat == 1)          next_s = S4;  else next_s = S2;////// 1010---提取10 S4: if(i_dat == 0)          next_s = S5;  else next_s = S1;  S5: if(i_dat == 1)          next_s = S0;  else next_s = S0;  default: next_s = S0;endcaseend/**************************時序邏輯的輸出*******************************/ always @(posedge clk or  posedge asy_rst)begin if(asy_rst) begin o_detect <= 0;  end  else case(curr_s) S0,S1,S2,S3,S4: begin o_detect <= 0;  end  S5:  begin  if(i_dat ==1 )  o_detect <= 1;  end default : begin o_detect <= 0; end endcaseend endmodule

/////////////////////////////////////testbench/////////////////////////////////////module seq_detect_sim;parameter CLK_PERIOD = 10; //仿真周期10ns=100Mparameter RST_CYCLE = 5; //復(fù)位周期數(shù)parameter RST_TIME = RST_CYCLE * CLK_PERIOD;  reg sim_clk;reg sim_asy_rst; initialbegin sim_clk = 0; sim_asy_rst = 1; #RST_TIME sim_asy_rst = 0;end always #(CLK_PERIOD/2) sim_clk = ~sim_clk;/******************************************************/parameter I_WD = 1;parameter O_WD = 1;parameter IN_SEQ = 32'b00101101_01011000_10110111_01010101; reg [4:0]cnt;reg sim_i_val;always @(posedge sim_clk or  posedge sim_asy_rst)begin if(sim_asy_rst) begin cnt <= 0; sim_i_val <= 0; end else begin cnt <= cnt +1; sim_i_val <= 1; endend wire [O_WD-1:0] o_detect;seq_detect seq_detect_u (.clk(sim_clk ),.asy_rst(sim_asy_rst ),.i_dat(IN_SEQ[cnt] ),.i_val(sim_i_val),.o_detect(o_detect) );endmodule
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉