|
经过网上的搜索及自己的实验,总结在Modelsim仿真中显示状态机名称的三种方法。下面以一个具体的实例进行讲解。
实例功能:引入状态机实现2分频,这里使用状态机完全只是为了说明如何在仿真中显示状态机名称。
状态转移图:
状态转移图
设计文件代码:
- 1 module fsm(
- 2 input clk,
- 3 input reset_n,
- 4 output reg clkout
- 5 );
- 6
- 7 parameter ONE = 2'b01,
- 8 ZERO = 2'b10;
- 9
- 10 reg [1:0]state;
- 11
- 12 always@(posedge clk or negedge reset_n)
- 13 if(!reset_n)begin
- 14 state <= ONE;
- 15 clkout <= 1'b1;
- 16 end
- 17 else begin
- 18 case(state)
- 19 ONE:begin
- 20 state <= ZERO;
- 21 clkout <= 1'b0;
- 22 end
- 23 ZERO:begin
- 24 state <= ONE;
- 25 clkout <= 1'b1;
- 26 end
- 27 endcase
- 28 end
- 29
- 30 endmodule
复制代码 testbench文件代码:
- 1 `timescale 1ns/1ns
- 2 `define CLK_PRIOD 20
- 3
- 4 module tb_fsm();
- 5
- 6 reg clk;
- 7 reg reset_n;
- 8 wire clkout;
- 9
- 10 fsm inst_fsm(
- 11 .clk(clk),
- 12 .reset_n(reset_n),
- 13 .clkout(clkout)
- 14 );
- 15
- 16 initial clk = 1;
- 17 always #(`CLK_PRIOD/2) clk = ~clk;
- 18
- 19 initial begin
- 20 reset_n = 0;
- 21 #201
- 22 reset_n = 1;
- 23 #500;
- 24 $stop;
- 25 end
- 26
- 27 endmodule
复制代码 仿真波形:
未处理
在波形图中,看到状态机状态只能以各种进制的数进行显示,当状态比较多的时候不太便于查看波形查找一些问题,下面将用3种不同的方式对状态机状态以名称的形式显示在波形图中。
static/image/hrline/line3.png
方法一:在testbench文件中对设计文件中的各种状态进行映射
实现过程:
在tb文件加入一个reg变量monitor_state,将设计文件中的状态state映射到monitor_state,通过映射将不同的状态state在tb文件中通过monitor_state用字符串表示,具体实现代码如下。与开始相比,tb文件增加了9~16行的代码,在modelsim波形显示窗口将信号monitor_state添加进行,将数据显示格式设置为ASCII码,这样就能看到monitor_state信号名称就显示为状态机名了,并且与state是一一对应的。
注:这里的monitor_state的位宽设置是根据状态名称最长字符的个数确定的,一个ASCII码字符要用8bit表示,这里最长的是4个字符,所以这里设置的位宽是32位。
- 1 `timescale 1ns/1ns
- 2 `define CLK_PRIOD 20
- 3 module tb_fsm();
- 4 reg clk;
- 5 reg reset_n;
- 6 wire clkout;
- 7 reg [31:0]monitor_state;
- 8
- 9 parameter ONE = 2'b01,
- 10 ZERO = 2'b10;
- 11
- 12 always@(inst_fsm.state)
- 13 case(inst_fsm.state)
- 14 ONE: monitor_state = "ONE ";
- 15 ZERO: monitor_state = "ZERO";
- 16 endcase
- 17
- 18 fsm inst_fsm(
- 19 .clk(clk),
- 20 .reset_n(reset_n),
- 21 .clkout(clkout)
- 22 );
- 23
- 24 initial clk = 1;
- 25 always #(`CLK_PRIOD/2) clk = ~clk;
- 26
- 27 initial begin
- 28 reset_n = 0;
- 29 #201
- 30 reset_n = 1;
- 31 #500;
- 32 $stop;
- 33 end
- 34 endmodule
复制代码 仿真波形:
方法1
static/image/hrline/line3.png
方法二:在testbench文件中对设计文件中的状态机编码进行重定义
实现过程:
在tb文件中将设计文件中的状态机编码用 defpara 进行重定义,具体可见下面代码8、9行,这里就涉及到重定义前后状态机状态寄存器的位宽发生了变化,重定义后的位宽变成了32位,这样就需要在设计文件中将状态寄存器state的位宽也设置成32bit。即将设计文件代码的第10行代码更改为 “reg [31:0]state;” 。这种情况不需要在波形文件额外添加信号,直接让状态机状态寄存器显示状态名。仿真波形见下面。
- 1 `timescale 1ns/1ns
- 2 `define CLK_PRIOD 20
- 3 module tb_fsm();
- 4 reg clk;
- 5 reg reset_n;
- 6 wire clkout;
- 7
- 8 defparam inst_fsm.ONE = "ONE ";
- 9 defparam inst_fsm.ZERO = "ZERO";
- 10
- 11 fsm inst_fsm(
- 12 .clk(clk),
- 13 .reset_n(reset_n),
- 14 .clkout(clkout)
- 15 );
- 16
- 17 initial clk = 1;
- 18 always #(`CLK_PRIOD/2) clk = ~clk;
- 19
- 20 initial begin
- 21 reset_n = 0;
- 22 #201
- 23 reset_n = 1;
- 24 #500;
- 25 $stop;
- 26 end
- 27 endmodule
复制代码 仿真波形:
static/image/hrline/line3.png
方法三:使用虚拟对象显示状态机名称
实现过程:
该种方法不需要对设计代码和tb代码进行更改,这个只需要在modelsim软件上进行一些Tcl命令的操作,首先使用ModelSim的virtual type命令定义一个新的枚举类型(FSM_TYPE),该枚举类型可以在随后的仿真中使用,其命令格式为:virtual type { {val1 s1} { val2 s2} … { valn sn} } newVirtualType,其中val表示枚举值,s表示枚举名。而newVirtualType表示新的枚举类型名称。
注:virtual type与 { 之间,里面的 {} 与 {} 之间,} 与newVirtualType 一定要有空格。
具体在本实例中在使用最开始的tb文件进行仿真后,然后再modelsim软件的tcl console窗口依次输入如下命令:
- 1 virtual type { {2‘b01 ONE} { 2'b10 ZERO} } state_type
-
- 2 virtual function {(state_type)/inst_fsm/state} fsm_state
-
- 3 add wave -color pink /inst_fsm/fsm_state
复制代码
方法3脚本
3条命令的作用分别为:
1、使用ModelSim的virtual type命令定义一个新的枚举类型state_type
2、将需要显示的信号(/inst_fsm/state,设计文件中状态寄存器)进行类型转换,转换成一个新的信号fsm_state
3、将新的信号fsm_state加入到wave窗口中
仿真波形:
方法3
该种方法的实现可参考:https://www.cnblogs.com/ZcsTech/p/3504416.html
总结:
以上三种方法均能实现在Modelsim仿真中显示状态机名称,各有特点,读者可以根据自己的习惯选择其中一种方法即可,这个就是能让在仿真波形时更加直观的看到状态转移的跳转情况。
|
-
medlsim命令
|