在使用Verilog编写有限状态机等逻辑的时候,状态机的各个状态通常以参数表示(如IDLE等)。当使用ModelSim仿真的时候,状态机变量在wave窗口中以二进制编码的形式显示,如下面所示,这种显示形式不是很直观,但我们可以使用ModelSim提供的命令将状态机变量以“文本”形式的参数名显示,从而有利于调试。
下面以一个实例来说明。
代码来源:http://www.cnblogs.com/oomusou/archive/2011/06/05/fsm_coding_style.html
源文件:
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_moore_3_always_best.v 5 Synthesizer : Quartus II 8.1 6 Description : 3 always block for moore fsm (BEST) 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm ( 11 clk, 12 rst_n, 13 w_i, 14 z_o 15 ); 16 17 input clk; 18 input rst_n; 19 input w_i; 20 output z_o; 21 22 parameter IDLE = 2'b00; 23 parameter S0 = 2'b01; 24 parameter S1 = 2'b10; 25 26 reg [1:0] curr_state; 27 reg [1:0] next_state; 28 reg z_o; 29 30 // state reg 31 always@(posedge clk or negedge rst_n) 32 if (~rst_n) curr_state <= IDLE; 33 else curr_state <= next_state; 34 35 // next state logic 36 always@(*) 37 case (curr_state) 38 IDLE : if (w_i) next_state = S0; 39 else next_state = IDLE; 40 S0 : if (w_i) next_state = S1; 41 else next_state = IDLE; 42 S1 : if (w_i) next_state = S1; 43 else next_state = IDLE; 44 default : next_state = IDLE; 45 endcase 46 47 // output logic 48 always@(*) 49 case (curr_state) 50 IDLE : z_o = 1'b0; 51 S0 : z_o = 1'b0; 52 S1 : z_o = 1'b1; 53 default : z_o = 1'b0; 54 endcase 55 56 endmodule
测试文件:
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_tb.v 5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9 6 Description : testbench for FSM 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm_tb; 11 12 reg clk = 1'b1; 13 reg rst_n = 1'b1; 14 reg w_i = 1'b0; 15 wire z_o; 16 17 // clk 18 always #10 clk = ~clk; 19 20 event after_rst; 21 22 // rst_n 23 initial begin 24 #6; // 6ns 25 rst_n = 1'b0; 26 #30; // 36ns 27 rst_n = 1'b1; 28 ->after_rst; 29 end 30 31 // w_i 32 initial begin 33 @(after_rst); 34 repeat(2)@(posedge clk); // 60ns 35 w_i <= 1'b1; 36 @(posedge clk); // 80 ns 37 w_i <= 1'b0; 38 @(posedge clk); // 100 ns 39 w_i <= 1'b1; 40 repeat(2)@(posedge clk); // 140 ns 41 w_i <= 1'b0; 42 @(posedge clk); // 160 ns 43 w_i <= 1'b1; 44 repeat(3)@(posedge clk); // 220 ns 45 w_i <= 1'b0; 46 end 47 48 initial begin 49 $fsdbDumpfile("simple_fsm.fsdb"); 50 $fsdbDumpvars(0, simple_fsm_tb); 51 end 52 53 simple_fsm u_simple_fsm ( 54 .clk (clk), 55 .rst_n (rst_n), 56 .w_i (w_i), 57 .z_o (z_o) 58 ); 59 60 endmodule
编写run.do文件
1 vlib work 2 vlog -novopt simple_fsm.v simple_fsm_tb.v 3 vsim -voptargs=+acc work.simple_fsm_tb 4 add wave * 5 virtual type { {0x00 IDLE} {0x01 S0} {0x02 S1} } FSM_TYPE 6 virtual function {(FSM_TYPE)/simple_fsm_tb/u_simple_fsm/curr_state} state1 7 add wave u_simple_fsm/curr_state 8 add wave -color pink /simple_fsm_tb/u_simple_fsm/state1 9 virtual function {(FSM_TYPE)/simple_fsm_tb/u_simple_fsm/next_state} state2 10 add wave u_simple_fsm/next_state 11 add wave -color pink /simple_fsm_tb/u_simple_fsm/state2 12 run 1000ns
编写run.bat
1 vsim -do run.do
在文件夹内双击run.bat即可。如果双击该批处理文件程序没有运行,说明vsim命令没有执行,解决方案请参考http://www.cnblogs.com/ZcsTech/p/3495578.html
运行结果如下:
virtual type {state0 state1 state2 state3} mystateType
virtual function {(mystateType)mysignal} myConvertedSignal
add wave myConvertedSignal
virtual type {{16'h2000 IDLE} {16'h1000 WRITE} {16'h40 DB_MSG} {16'h400 READ_SOF}} FSM_TYPE
virtual function {(FSM_TYPE)/ep_tb/ep_sim1/user_sim_host/target_sim_user/state} state1
add wave /ep_tb/ep_sim1/user_sim_host/target_sim_user/state1
virtual function {(FSM_TYPE)/ep_tb/ep_sim1/user_sim_host/target_sim_user/next_state} state2
add wave /ep_tb/ep_sim1/user_sim_host/target_sim_user/state2