芯路恒电子技术论坛

 找回密码
 立即注册
热搜: 合集
查看: 6447|回复: 0

在Modelsim仿真中显示状态机名称的3种方法

[复制链接]
  • TA的每日心情
    开心
    2021-1-26 21:41
  • 16

    主题

    41

    帖子

    273

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    273
    发表于 2018-9-16 21:18:16 | 显示全部楼层 |阅读模式
       经过网上的搜索及自己的实验,总结在Modelsim仿真中显示状态机名称的三种方法。下面以一个具体的实例进行讲解。
    实例功能:引入状态机实现2分频,这里使用状态机完全只是为了说明如何在仿真中显示状态机名称。
    状态转移图:

    状态转移图

    状态转移图

    设计文件代码:
    1. 1         module fsm(
    2.     2                 input clk,
    3.     3                 input reset_n,
    4.     4                 output reg clkout
    5.     5         );
    6.     6
    7.     7         parameter ONE  = 2'b01,
    8.     8                ZERO = 2'b10;
    9.     9                                  
    10.     10        reg [1:0]state;
    11.     11
    12.     12        always@(posedge clk or negedge reset_n)
    13.     13        if(!reset_n)begin
    14.     14                state <= ONE;
    15.     15                clkout <= 1'b1;
    16.     16        end
    17.     17        else begin
    18.     18                case(state)
    19.     19                        ONE:begin
    20.     20                                state <= ZERO;
    21.     21                                clkout <= 1'b0;
    22.     22                        end
    23.     23                        ZERO:begin
    24.     24                                state <= ONE;
    25.     25                                clkout <= 1'b1;
    26.     26                        end
    27.     27                endcase
    28.     28        end
    29.     29
    30.     30        endmodule
    复制代码
    testbench文件代码:
    1. 1         `timescale 1ns/1ns
    2. 2         `define CLK_PRIOD 20
    3. 3
    4. 4         module tb_fsm();
    5. 5
    6. 6                 reg clk;
    7. 7                 reg reset_n;
    8. 8                 wire clkout;
    9. 9
    10. 10                fsm inst_fsm(
    11. 11                        .clk(clk),
    12. 12                        .reset_n(reset_n),
    13. 13                        .clkout(clkout)
    14. 14                );
    15. 15               
    16. 16                initial clk = 1;
    17. 17                always #(`CLK_PRIOD/2) clk = ~clk;
    18. 18               
    19. 19                initial begin
    20. 20                        reset_n = 0;
    21. 21                        #201
    22. 22                        reset_n = 1;
    23. 23                        #500;
    24. 24                        $stop;
    25. 25                end
    26. 26
    27. 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. 1         `timescale 1ns/1ns
    2.     2         `define CLK_PRIOD 20
    3.     3         module tb_fsm();
    4.     4                 reg clk;
    5.     5                 reg reset_n;
    6.     6                 wire clkout;
    7.     7                 reg [31:0]monitor_state;
    8.     8                
    9.     9         parameter ONE  = 2'b01,
    10.     10              ZERO = 2'b10;
    11.     11
    12.     12                always@(inst_fsm.state)
    13.     13                case(inst_fsm.state)
    14.     14                        ONE:  monitor_state = "ONE ";
    15.     15                        ZERO: monitor_state = "ZERO";
    16.     16                endcase
    17.     17
    18.     18                fsm inst_fsm(
    19.     19                        .clk(clk),
    20.     20                        .reset_n(reset_n),
    21.     21                        .clkout(clkout)
    22.     22                );
    23.     23               
    24.     24                initial clk = 1;
    25.     25                always #(`CLK_PRIOD/2) clk = ~clk;
    26.     26               
    27.     27                initial begin
    28.     28                        reset_n = 0;
    29.     29                        #201
    30.     30                        reset_n = 1;
    31.     31                        #500;
    32.     32                        $stop;
    33.     33                end
    34.     34        endmodule
    复制代码
    仿真波形:

    方法1

    方法1


    static/image/hrline/line3.png
    方法二:在testbench文件中对设计文件中的状态机编码进行重定义
    实现过程:
       在tb文件中将设计文件中的状态机编码用 defpara 进行重定义,具体可见下面代码8、9行,这里就涉及到重定义前后状态机状态寄存器的位宽发生了变化,重定义后的位宽变成了32位,这样就需要在设计文件中将状态寄存器state的位宽也设置成32bit。即将设计文件代码的第10行代码更改为 “reg [31:0]state;” 。这种情况不需要在波形文件额外添加信号,直接让状态机状态寄存器显示状态名。仿真波形见下面。
    1. 1         `timescale 1ns/1ns
    2.     2         `define CLK_PRIOD 20
    3.     3         module tb_fsm();
    4.     4                 reg clk;
    5.     5                 reg reset_n;
    6.     6                 wire clkout;
    7.     7
    8.     8         defparam        inst_fsm.ONE  = "ONE ";
    9.     9         defparam        inst_fsm.ZERO = "ZERO";
    10.     10
    11.     11                fsm inst_fsm(
    12.     12                        .clk(clk),
    13.     13                        .reset_n(reset_n),
    14.     14                        .clkout(clkout)
    15.     15                );
    16.     16               
    17.     17                initial clk = 1;
    18.     18                always #(`CLK_PRIOD/2) clk = ~clk;
    19.     19               
    20.     20                initial begin
    21.     21                        reset_n = 0;
    22.     22                        #201
    23.     23                        reset_n = 1;
    24.     24                        #500;
    25.     25                        $stop;
    26.     26                end
    27.     27        endmodule
    复制代码
    仿真波形:
    方法2.JPG

    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. 1  virtual type { {2‘b01 ONE} { 2'b10 ZERO} } state_type
    2.      
    3. 2 virtual function {(state_type)/inst_fsm/state} fsm_state
    4.      
    5. 3 add wave -color pink /inst_fsm/fsm_state
    复制代码

    方法3脚本

    方法3脚本

    3条命令的作用分别为:
    1、使用ModelSim的virtual type命令定义一个新的枚举类型state_type
    2、将需要显示的信号(/inst_fsm/state,设计文件中状态寄存器)进行类型转换,转换成一个新的信号fsm_state
    3、将新的信号fsm_state加入到wave窗口中
    仿真波形:

    方法3

    方法3

    该种方法的实现可参考:https://www.cnblogs.com/ZcsTech/p/3504416.html
    总结:
       以上三种方法均能实现在Modelsim仿真中显示状态机名称,各有特点,读者可以根据自己的习惯选择其中一种方法即可,这个就是能让在仿真波形时更加直观的看到状态转移的跳转情况。

    medlsim命令

    medlsim命令
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|小黑屋|Archiver|芯路恒电子技术论坛 |鄂ICP备2021003648号

    GMT+8, 2024-3-29 00:34 , Processed in 0.113332 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

    快速回复 返回顶部 返回列表