我们再用modelsim进行状态机仿真时,状态机state显示通常是以进制数字表示,我们更喜欢的是需要用当前状态表示(例如S0、S1等),这样以文本形式表示更利于调试。
下面用一个实例来说明
源文件:
module fsm_sale
(
input clk ,
input rst_n ,
input [1:0] in ,
output reg [1:0] out ,
output reg out_vld
);
reg [3:0] state ;
reg [3:0] n_state ;
localparam S0 = 4'b0001 ;
localparam S1 = 4'b0010 ;
localparam S2 = 4'b0100 ;
localparam S3 = 4'b1000 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
state <= S0;
else
state <= n_state;
end
always @(*)begin
case(state)
S0: begin
if(in==1)
n_state = S1;
else if(in==2)
n_state = S2;
else
n_state = state;
end
S1: begin
if(in==1)
n_state = S2;
else if(in==2)
n_state = S3;
else
n_state = state;
end
S2: begin
if(in==1)
n_state = S3;
else if(in==2)
n_state = S0;
else
n_state = state;
end
S3: begin
if(in==1 || in==2) // in != 0也行
n_state = S0;
else
n_state = state;
end
default:n_state = S0;
endcase
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
out <= 0;
else if(state ==S3 && in==2)
out <= 1;
else
out <= 0;
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)
out_vld <= 0;
else if((state ==S2 && in==2) || (state ==S3 && in!=0))
out_vld <= 1;
else
out_vld <= 0;
end
endmodule
测试文件
`timescale 1ns/1ps //时间精度
`define Clock 20 //时钟周期
module FSM_tb;
reg clk ;
reg rst_n ;
reg [1:0] in ;
wire [1:0] out ;
wire out_vld ;
fsm_sale u_fsm_sale
(
.clk (clk ),
.rst_n (rst_n ),
.in (in ),
.out (out ),
.out_vld (out_vld )
);
localparam S0 = 4'b0001 ;
localparam S1 = 4'b0010 ;
localparam S2 = 4'b0100 ;
localparam S3 = 4'b1000 ;
//2字符16位
reg [15:0] state_name ;
always@(*)begin
case(u_fsm_sale.state)
S0: state_name = "S0";
S1: state_name = "S1";
S2: state_name = "S2";
S3: state_name = "S3";
default:state_name = "S0";
endcase
end
initial begin
clk = 1;
forever
#(`Clock/2) clk = ~clk;
end
initial begin
rst_n = 0; #(`Clock*20+1);
rst_n = 1;
end
initial begin
#1;
in = 0;
#(`Clock*20+1); //初始化完成
//情况1--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况2--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况3--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况4--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况5--------------------------
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
$stop;
end
endmodule
这里我用的quartus对上述代码进行编译,然后用modelsim进行状态测试。
第一步:在modelsim的transcript命令窗口中定义一个新的枚举(FSM_TYPE)
virtual type {
{4’b0001 S0}
{4’b0010 S1}
{4’b0100 S2}
{4’b1000 S3}
} FSM_TYPE;
第二步:将需要的信号(state)进行转换成新的信号(state_new),此时需要把信号地址写清楚;
virtual function {(FSM_TYPE)/FSM_tb/u_fsm_sale/state} state_new
第三步:将新的信号添加到wave窗口中,重置信号,再运行run -all
add wave -color green /FSM_tb/u_fsm_sale/state_new
最后部分运行结果如下:
参考文献:在ModelSim波形图中以参数名显示变量