狀态機代碼寫法
一段式
在一段狀态機中,使用時序邏輯既描述狀态的轉移又描述輸入輸出。
二段式
分兩段狀态機,在第一段狀态機中描述狀态的轉移,在第二段中描述輸入輸出。
三段式
分三段。第一段中采用時序邏輯描述狀态的轉移,第二段中采用組合邏輯,判斷轉移條件,描述轉移規律,第三段狀态機中描述狀态輸出,可使用組合邏輯或者時序邏輯。
案例一(簡單可樂機)
代碼以及輸出
//cola.v
module cola(
//輸入信号 時鐘信号 複位信号 投币
input wire clk,
input wire rst_n,
input wire money,
//輸出信号
output reg cola
);
//定義狀态參數 使用獨熱碼編碼
parameter IDLE = 3'b000;
parameter ONE = 3'b010;
parameter TWO = 3'b100;
//獨熱碼 每個狀态下編碼隻有一位是高電平 其他都是低電平 幾個狀态用幾位編碼
reg[2:0] state;
always @(posedge clk or negedge rst_n)
if(rst_n == 1'b0)//rst==1 複位信号有效
state <= IDLE;
else case(state)
IDLE:if(money == 1'b1)
state <= ONE;
else
state <= IDLE;
ONE: if(money == 1'b1)
state <= TWO;
else
state <= ONE;
TWO:if(money == 1'b1)
state <= IDLE;
else
state <= TWO;
default:state <= IDLE;
endcase
always @ (posedge clk or negedge rst_n)//begin
if(rst_n == 1'b0)
cola <= 1'b0;
else if((state == TWO)&&(money == 1'b1))
cola <= 1'b1;
else
cola <= 1'b0;
//end
endmodule
//cola_tb.v
`timescale 1ns/1ns
module cola_tb();
reg clk;
reg rst_n;
reg money;
wire cola;
//初始化系統時鐘,全局複位
initial begin
clk = 1'b1;
rst_n <= 1'b0;//複位有效
#20
rst_n <= 1'b1;//複位無效
end
//clk模拟時鐘系統 每10ns電平翻轉一次 周期為20ns 頻率為 50mhz
always #10 clk = ~clk;
//産生輸入随機數 模拟投币一進制的情況
always @ (posedge clk or negedge rst_n)
if(rst_n == 1'b0)
money <= 1'b0;
else
money <= {$random}%2;//取模求餘數 産生随機數 0、1
wire[2:0] state = cola0.state;
initial
begin
$timeformat(-9,0,"ns",6);
$monitor("@time %t: money=%b state=%b cola=%b",$time,money,state,cola);
end
//開始執行個體化
cola cola0(
.clk(clk),
.rst_n(rst_n),
.money(money),
.cola(cola)
);
endmodule
/*run
# @time 0ns: money=0 state=000 cola=0
# @time 40ns: money=1 state=000 cola=0
# @time 60ns: money=1 state=010 cola=0
# @time 80ns: money=1 state=100 cola=0
run
# @time 100ns: money=1 state=000 cola=1
# @time 120ns: money=1 state=010 cola=0
# @time 140ns: money=1 state=100 cola=0
# @time 160ns: money=0 state=000 cola=1
# @time 180ns: money=1 state=000 cola=0
run
# @time 200ns: money=1 state=010 cola=0
# @time 220ns: money=0 state=100 cola=0
# @time 240ns: money=1 state=100 cola=0
# @time 260ns: money=1 state=000 cola=1
# @time 280ns: money=0 state=010 cola=0
add wave \
sim:/cola_tb/clk \
sim:/cola_tb/rst_n \
sim:/cola_tb/money \
sim:/cola_tb/cola \
sim:/cola_tb/state
run
# @time 300ns: money=1 state=010 cola=0
# @time 320ns: money=0 state=100 cola=0
# @time 340ns: money=1 state=100 cola=0
# @time 360ns: money=0 state=000 cola=1
# @time 380ns: money=1 state=000 cola=0
run
# @time 400ns: money=1 state=010 cola=0
# @time 420ns: money=0 state=100 cola=0
# @time 440ns: money=1 state=100 cola=0
# @time 460ns: money=0 state=000 cola=1
# @time 480ns: money=0 state=000 cola=0
run
# @time 520ns: money=1 state=000 cola=0
# @time 540ns: money=0 state=010 cola=0
# @time 560ns: money=1 state=010 cola=0
# @time 580ns: money=1 state=100 cola=0
run
# @time 600ns: money=1 state=000 cola=1
# @time 620ns: money=1 state=010 cola=0
# @time 640ns: money=0 state=100 cola=0
*/
仿真
案例二(可以找零的可樂機)
簡單分析一下它的狀态:
一聽可樂是2.5元
輸入:0.5、1
輸出:不出可樂不找零、不出可樂找零 、出可樂不找零、出可樂找零
狀态:不投币(00)、投0.5元(01)、投1元(10)
不出可樂不找零(00)、出可樂找零(01)、出可樂不找零(10)
代碼:
//cola2.v
module cola2(
input wire rst,
input wire clk,
input wire pi_money_half,
input wire pi_money_one,
output reg po_money, //找零
output reg po_cola//出可樂
);
//五種狀态使用獨熱碼
parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF= 5'b01000;
parameter TWO = 5'b10000;
reg [4:0]state;
wire [1:0] pi_money;
assign pi_money = {pi_money_one,pi_money_half};//00 01 10
//第一段狀态機,描述目前狀态state如何根據輸入跳轉到下一個狀态
always @ (posedge clk or posedge rst)begin
if(rst == 1'b1)begin
state <= IDLE;
end
else begin
case(state)
IDLE:begin
if(pi_money == 2'b01)begin//pi_one = 0 pi_half= 1 輸入0.5
state <= HALF;
end
else if(pi_money == 2'b10)begin
state <= ONE;
end
else begin
state <= IDLE;
end
end
HALF:begin
if(pi_money == 2'b01) begin
state <= ONE;
end
else if(pi_money == 2'b10)begin
state <= ONE_HALF;
end
else begin
state <= HALF;
end
end
ONE:begin
if(pi_money == 2'b01)begin
state <= ONE_HALF;
end
else if(pi_money == 2'b10)begin
state <= TWO;
end
else begin
state <= ONE;
end
end
ONE_HALF:begin
if(pi_money == 2'b01)begin
state <= TWO;
end
if(pi_money == 2'b10)begin
state <= IDLE;
end
else begin
state <= ONE_HALF;
end
end
TWO:begin
if(pi_money == 2'b01)begin
state <= IDLE;
end
else if(pi_money == 2'b10)begin
state <= IDLE;
end
else begin
state <= TWO;
end
end
default://begin
state <= IDLE;
//end
endcase
end
end
//第二段狀态機 描述目前狀态state和輸入pi_money如何影響po_cola的輸出
always @ (posedge clk or posedge rst)begin
if(rst == 1'b1)begin
po_cola <= 1'b0;
end
else if((state == TWO&&pi_money == 2'b01)||(state == TWO&&pi_money == 2'b10)||(state == ONE_HALF&&pi_money == 2'b10))begin
po_cola <= 1'b1;
end
else begin
po_cola <= 1'b0;
end
end
//第二段狀态機 描述目前狀态state和輸入pi_money如何影響po_money輸出
always @ (posedge clk or posedge rst)begin
if(rst == 1'b1)begin
po_money <= 1'b0;
end
else if((state == TWO)&&(pi_money == 2'b10))begin
po_money <= 1'b1;
end
else begin
po_money <= 1'b0;
end
end
endmodule
tb
//cola2_tb.v
`timescale 1ns/1ns
module cola2_tb();
reg clk;
reg rst;
reg pi_money_one;
reg pi_money_half;
reg random_data;//随機數
wire po_money;
wire po_cola;
//初始化系統時鐘、全局複位
initial begin
clk = 1'b1;
rst <= 1'b1;
#20 //延時20ns
rst <= 1'b0;
end
//clk:模拟系統時鐘,每10ns電平翻轉一次,周期為20ns,頻率50mhz
always #10 clk = ~clk;
//radom_data:産生随機數 0 1
always @(posedge clk or posedge rst)begin
if(rst == 1'b1)begin
random_data <= 1'b0;
end
else begin
random_data <= {$random}%2;
end
end
//pi_money_one:模拟投入一進制的情況
always @(posedge clk or posedge rst)begin
if(rst == 1'b1)begin
pi_money_one <= 1'b0;
end
else begin
pi_money_one <=random_data;
end
end
//pi_money_half:模拟投入五毛的情況
always @(posedge clk or posedge rst)begin
if(rst == 1'b1)begin
pi_money_half <= 1'b0;
end
else begin
pi_money_half <= ~random_data;//不可以同時投入五毛和一進制
end
end
//将rtl子產品中的内部信号引入到testbench子產品中觀察
wire [4:0] state = cola2_0.state;
wire [1:0] pi_money = cola2_0.pi_money;
initial begin
$timeformat(-9,0,"ns",6);
$monitor("@time %t :pi_money_one=%b pi_money_half=%b pi_money=%b state=%b po_cola=%b po_money=%b",$time,pi_money_one,pi_money_half,pi_money,state,po_cola,po_money);
end
//例化
cola2 cola2_0(
.clk(clk),
.rst(rst),
.pi_money_one(pi_money_one),
.pi_money_half(pi_money_half),
.po_cola(po_cola),
.po_money(po_money)
);
endmodule
/*run
# @time 0ns :pi_money_one=0 pi_money_half=0 pi_money=00 state=00001 po_cola=0 po_money=0
# @time 40ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=0 po_money=0
# @time 60ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
# @time 80ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
run
# @time 100ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time 120ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time 140ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=10000 po_cola=0 po_money=0
# @time 160ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=1
# @time 180ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
run
# @time 200ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 220ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time 240ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time 260ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 280ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
run
# @time 300ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time 320ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 340ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
# @time 360ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
# @time 380ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=01000 po_cola=0 po_money=0
run
# @time 400ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 420ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time 440ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time 460ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 480ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
run
# @time 500ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00010 po_cola=0 po_money=0
# @time 520ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time 540ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 560ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
# @time 580ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
run
# @time 600ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 620ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time 640ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time 660ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=10000 po_cola=0 po_money=0
# @time 680ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
run
# @time 700ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00010 po_cola=0 po_money=0
# @time 720ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
# @time 740ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 760ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=0
# @time 780ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00010 po_cola=0 po_money=0
run
# @time 800ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=01000 po_cola=0 po_money=0
# @time 820ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=0
# @time 840ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time 860ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=10000 po_cola=0 po_money=0
# @time 880ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00001 po_cola=1 po_money=1
run
# @time 900ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00010 po_cola=0 po_money=0
# @time 920ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00100 po_cola=0 po_money=0
# @time 940ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=10000 po_cola=0 po_money=0
# @time 960ns :pi_money_one=1 pi_money_half=0 pi_money=10 state=00001 po_cola=1 po_money=1
# @time 980ns :pi_money_one=0 pi_money_half=1 pi_money=01 state=00100 po_cola=0 po_money=0
*/
仿真
困了,累了,懶,一天寫一個都沒有。。。。