經過網上的搜尋及自己的實驗,總結在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種不同的方式對狀态機狀态以名稱的形式顯示在波形圖中。
方法一:在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
仿真波形:
方法二:在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
仿真波形:
方法三:使用虛拟對象顯示狀态機名稱
實作過程:
該種方法不需要對設計代碼和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視窗依次輸入如下指令:
virtual type { {2‘b01 ONE} { 2'b10 ZERO} } state_type
virtual function {(state_type)/inst_fsm/state} fsm_state
add wave -color pink /inst_fsm/fsm_state
3條指令的作用分别為:
1、使用ModelSim的virtual type指令定義一個新的枚舉類型state_type
2、将需要顯示的信号(/inst_fsm/state,設計檔案中狀态寄存器)進行類型轉換,轉換成一個新的信号fsm_state
3、将新的信号fsm_state加入到wave視窗中
最終在波形圖形中金可以看到新的信号fsm_state是與設計檔案中狀态寄存器state同步變化,并且以字元名稱顯示。
仿真波形:
該種方法的實作可參考:https://www.cnblogs.com/ZcsTech/p/3504416.html
總結:
以上三種方法均能實作在Modelsim仿真中顯示狀态機名稱,各有特點,讀者可以根據自己的習慣選擇其中一種方法即可,這個就是能讓在仿真波形時更加直覺的看到狀态轉移的跳轉情況。