日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机

發布時間:2024/1/1 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接:https://blog.csdn.net/qq_34070723/article/details/100737225
作者:King阿金

目錄

1.狀態機原理與三段式狀態機

2.狀態機示例

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

2.2序列檢測器


1.狀態機原理與三段式狀態機

MOORE 與 MEALEY 狀態機的特征?
Moore 狀態機的輸出僅與當前狀態值有關, 且只在時鐘邊沿到來時才會有狀態變化。次態=f(現狀,輸入),輸出=f(現狀)
Mealy 狀態機的輸出不僅與當前狀態值有關, 而且與當前輸入值有關。次態=f(現狀,輸入),輸出=f(現狀,輸入)
描述同一個事務,mealy的狀態更少。

通用mealy三段式狀態機(建議實際工程中采用的結構)

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

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

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

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

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

    另一個版本:用Verilog實現接受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;
  • //每個時鐘只產生一次狀態變化
  • always @(posedge clk or posedge asy_rst)
  • begin
  • if(asy_rst)
  • curr_s <= S0;
  • else
  • curr_s <= next_s;
  • end
  • //產生的下一狀態的組合邏輯
  • always @(*)
  • begin
  • next_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;
  • endcase
  • end
  • /**************************時序邏輯的輸出*******************************/
  • 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
  • endcase
  • end
  • /***************************不采用狀態機的方法**********************************/
  • reg [3:0] add_in;//內部計算輸入的錢的和
  • 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;
  • end
  • end
  • endmodule
  • /testbench//
  • module auto_sell_sim;
  • parameter CLK_PERIOD = 10; //仿真周期10ns=100M
  • parameter RST_CYCLE = 5; //復位周期數
  • parameter RST_TIME = RST_CYCLE * CLK_PERIOD;
  • reg sim_clk;
  • reg sim_asy_rst;
  • initial
  • begin
  • 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;//產生0-5的隨機數
  • 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
  • end
  • end
  • 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個狀態,最少(3)個寄存器進行狀態轉換(mealy)。

    ?題目:用狀態機實現 101101 的序列檢測。

    思路:

    畫出mealy狀態轉換圖,并進行化簡[1],灰色表示合并為一個:

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

  • //mealy狀態機
  • 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;
  • //101101
  • reg [5:0] curr_s;
  • reg [5:0] next_s;
  • //每個時鐘只產生一次狀態變化
  • always @(posedge clk or posedge asy_rst)
  • begin
  • if(asy_rst)
  • curr_s <= S0;
  • else
  • curr_s <= next_s;
  • end
  • //產生的下一狀態的組合邏輯
  • always @(*)
  • begin
  • next_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;
  • endcase
  • end
  • /**************************時序邏輯的輸出*******************************/
  • 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
  • endcase
  • end
  • endmodule
  • /testbench/
  • module seq_detect_sim;
  • parameter CLK_PERIOD = 10; //仿真周期10ns=100M
  • parameter RST_CYCLE = 5; //復位周期數
  • parameter RST_TIME = RST_CYCLE * CLK_PERIOD;
  • reg sim_clk;
  • reg sim_asy_rst;
  • initial
  • begin
  • 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;
  • end
  • end
  • 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
  • 參考資料
    [1]“101101”序列檢測器Verilog設計實例與VCS仿真(mealy型和moore型)

    總結

    以上是生活随笔為你收集整理的Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。