赞
踩
目录
TCL(Tool Command Language)是一种脚本编程语言,由John Ousterhout在1988年开发。TCL是一种通用的、高级的、解释执行的脚本语言,它特别适合用于快速原型开发、测试、自动化任务以及GUI开发。TCL语言设计简单,易于学习和使用,它具有可扩展性,可以通过添加库来扩展其功能。
ModelSim是由Mentor Graphics(现在是Siemens EDA的一部分)开发的一款行业标准的硬件描述语言(HDL)仿真工具。它支持多种HDL语言,包括VHDL、Verilog和SystemVerilog,用于验证数字电路和系统的设计。
TCL脚本与ModelSim的关系在于,ModelSim提供了对TCL脚本的支持,使得用户可以使用TCL脚本来控制仿真环境、运行仿真、管理项目、处理结果等。通过编写TCL脚本,用户可以自动化ModelSim的许多操作,提高工作效率,实现复杂的测试流程,以及进行批量处理。例如,用户可以编写TCL脚本来自动化测试套件的执行,收集和分析仿真结果,甚至修改仿真参数并重新运行仿真,从而实现更加高效的验证流程。
- `timescale 1ns/1ns
-
- module complex_fsm(
- input wire sys_clk , //系统时钟50MHz
- input wire sys_rst_n , //全局复位
- input wire pi_money_one , //投币1元
- input wire pi_money_half , //投币0.5元
-
- output reg po_money , //po_money为1时表示找零
- //po_money为0时表示不找零
- output reg po_cola //po_cola为1时出可乐
- //po_cola为0时不出可乐
- );
-
- //----------------------------------------------------------------------
- //parameter define
- //只有五种状态,使用独热码
- parameter IDLE = 5'b00001;
- parameter HALF = 5'b00010;
- parameter ONE = 5'b00100;
- parameter ONE_HALF = 5'b01000;
- parameter TWO = 5'b10000;
- //wire define
- wire [1:0] pi_money;
- //reg define
- reg [4:0] state;
- //----------------------------------------------------------------------
- //maincode
- //pi_money:为了减少变量的个数,我们用位拼接把输入的两个1bit信号拼接成1个2bit信号。投币方式可以为:不投币(00)、投0.5元(01)、投1元(10),每次只投一个币
- assign pi_money = {pi_money_one, pi_money_half};
- //第一段状态机,描述当前状态state如何根据输入跳转到下一状态
- always@(posedge sys_clk or negedge sys_rst_n)
- if(sys_rst_n == 1'b0)
- state <= IDLE; //任何情况下只要按复位就回到初始状态
- else case(state)
- IDLE : if(pi_money == 2'b01) //判断一种输入情况
- state <= HALF;
- else if(pi_money == 2'b10)//判断另一种输入情况
- state <= ONE;
- else
- state <= IDLE;
-
- HALF : if(pi_money == 2'b01)
- state <= ONE;
- else if(pi_money == 2'b10)
- state <= ONE_HALF;
- else
- state <= HALF;
-
- ONE : if(pi_money == 2'b01)
- state <= ONE_HALF;
- else if(pi_money == 2'b10)
- state <= TWO;
- else
- state <= ONE;
-
- ONE_HALF: if(pi_money == 2'b01)
- state <= TWO;
- else if(pi_money == 2'b10)
- state <= IDLE;
- else
- state <= ONE_HALF;
-
- TWO : if((pi_money == 2'b01) || (pi_money == 2'b10))
- state <= IDLE;
- else
- state <= TWO;
- //如果状态机跳转到编码的状态之外也回到初始状态
- default : state <= IDLE;
- endcase
-
- //第二段状态机,描述当前状态state和输入pi_money如何影响po_cola输出
- always@(posedge sys_clk or negedge sys_rst_n)
- if(sys_rst_n == 1'b0)
- po_cola <= 1'b0;
- else if((state == TWO && pi_money == 2'b01) || (state == TWO &&
- pi_money == 2'b10) || (state == ONE_HALF && pi_money == 2'b10))
- po_cola <= 1'b1;
- else
- po_cola <= 1'b0;
- //第二段状态机,描述当前状态state和输入pi_money如何影响po_money输出
- always@(posedge sys_clk or negedge sys_rst_n)
- if(sys_rst_n == 1'b0)
- po_money <= 1'b0;
- else if((state == TWO) && (pi_money == 2'b10))
- po_money <= 1'b1;
- else
- po_money <= 1'b0;
-
- endmodule

关于随机数可参考:Modelsim怎样在测试平台文件中快捷使用随机数?-CSDN博客
- `timescale 1ns/1ns
-
- module tb_complex_fsm();
-
- //----------------------------------------------------------------------
- //reg define
- reg sys_clk;
- reg sys_rst_n;
- reg pi_money_one;
- reg pi_money_half;
- reg random_data_gen;
-
- //wire define
- wire po_cola;
- wire po_money;
- //----------------------------------------------------------------------
- //初始化系统时钟、全局复位
- initial begin
- sys_clk = 1'b1;
- sys_rst_n <= 1'b0;
- #20
- sys_rst_n <= 1'b1;
- end
- //sys_clk:模拟系统时钟,每10ns电平翻转一次,周期为20ns,频率为50MHz
- always #10 sys_clk = ~sys_clk;
- //random_data_gen:产生非负随机数0、1
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- random_data_gen <= 1'b0;
- else
- random_data_gen <= {$random} % 2;
-
- //pi_money_one:模拟投入1元的情况
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- pi_money_one <= 1'b0;
- else
- pi_money_one <= random_data_gen;
- //pi_money_half:模拟投入0.5元的情况
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- pi_money_half <= 1'b0;
- else
- pi_money_half <= ~random_data_gen; //取反是因为一次只能投一个币,即pi_money_one和pi_money_half不能同时为1
-
- //------------------------------------------------------------
- //将RTL模块中的内部信号引入到Testbench模块中进行观察打印
- wire [4:0] state = complex_fsm_inst.state;
- wire [1:0] pi_money = complex_fsm_inst.pi_money;
-
- initial begin
- $timeformat(-9, 0, "ns", 6);
- $monitor("@time %t: pi_money_one=%b pi_money_half=%b pi_money=%b state=%b po_cola=%b po_money=%b", $time, pi_money_one, pi_money_half, pi_money, state, po_cola, po_money);
- end
- //------------------------------------------------------------
- complex_fsm complex_fsm_inst(
- .sys_clk (sys_clk ), //input sys_clk
- .sys_rst_n (sys_rst_n ), //input sys_rst_n
- .pi_money_one (pi_money_one ), //input pi_money_one
- .pi_money_half (pi_money_half ), //input pi_money_half
-
- .po_cola (po_cola ), //output po_money
- .po_money (po_money ) //output po_cola
- );
-
- endmodule

1) `quit -sim` :退出仿真,如果当前modelsim中具有仿真运行,可以将其中止并退出仿真界面。
2)`.main clear ` :清除modelsim Transcript中的内容
3)`vlog "../src*.v" `:vlog为编译的意思,则../src/*.v代表路径。因为FPGA设计文件在src中,所以需要用../退到上一级文件夹,再选择src/*.v(即该文件夹下的所有.v文件)。如果不需要全部编译,也可以指定文件(vlog "../src/complex_fsm.v)。
4) `vsim`:这是ModelSim/QuestaSim的仿真命令,用于启动仿真。
5)`-t ns`这个选项指定了仿真的时间单位。在这个例子中,`-t ns`表示时间单位是纳秒(nanoseconds)。
6)`-voptargs=+acc`:这个选项用于传递参数给仿真优化工具(vopt)。`+acc`是一个特定的参数,它启用了额外的信号可访问性,这通常用于波形查看或交互式调试。`+acc`选项会使得更多的信号在仿真中可见,这可能会影响仿真的性能,因为需要跟踪更多的信号。
7)`work.tb_complex_fsm`: 这部分指定了要仿真的测试台(testbench)。`work`是ModelSim/QuestaSim中默认的库名,`tb_complex_fsm`是测试台的名字。在ModelSim/QuestaSim中,所有编译好的设计和测试台都存储在一个名为“work”的库中,除非你在编译时指定了其他的库名。
8)`add wave -driver {tb_complex_fsm}`:这条命令在波形显示中添加一个分隔线,用以区分不同的信号组。`{tb_complex_fsm}`是分隔线的标签。
9)`add wave tb_complex_fsm/*`: 这条命令将`tb_complex_fsm`测试台中所有的信号添加到波形显示中。``是一个通配符,表示添加所有信号。
10)`add wave -divider {complex_fsm}`: 这条命令在波形显示中添加一个分隔线,用以区分不同的信号组。`{complex_fsm}`是分隔线的标签。
11)`add wave -radix decimal tb_complex_fsm/complex_fsm_inst/*`: 这条命令将`tb_complex_fsm/complex_fsm_inst/`下的所有信号添加到波形显示中,并且设置这些信号的显示基数为十进制。这意味着这些信号的值将以十进制形式显示,而不是默认的二进制或十六进制。
12)`virtual function {(vir_new_signal)tb_complex_fsm/complex_fsm_inst/state} new_state`:这条命令创建了一个虚拟信号`new_state`,它是基于`tb_complex_fsm/complex_fsm_inst/state`信号的函数。这里的`vir_new_signal`可能是一个自定义的函数,用于处理`state`信号并生成`new_state`虚拟信号。
13)`add wave -color red -itemcolor blue tb_complex_fsm/complex_fsm_inst/new_state`: 这条命令将虚拟信号`new_state`添加到波形显示中,并设置该信号的波形颜色为红色,信号项的颜色为蓝色。
- #---------------------------------------------------------------------
- #基础配置
- quit -sim
- .main clear
-
- #---------------------------------------------------------------------
- #包含文件
- vlog "../src/*.v"
- vlog "*.v"
- #开始仿真
- vsim -t ns -voptargs=+acc work.tb_complex_fsm
-
- #---------------------------------------------------------------------
- # 添加虚拟类型
- virtual type {
- {01 IDLE}
- {02 HALF}
- {04 ONE}
- {08 ONE_HALF}
- {16 TWO}
- } vir_new_signal
-
- #----------------------------------------------------------------------
- #添加波形
- add wave -divider {tb_complex_fsm}
-
- add wave tb_complex_fsm/*
- add wave -divider {complex_fsm_inst}
- add wave -radix decimal tb_complex_fsm/complex_fsm_inst/*
- virtual function {(vir_new_signal)tb_complex_fsm/complex_fsm_inst/state} new_state
- add wave -color red -itemcolor blue tb_complex_fsm/complex_fsm_inst/new_state
-
- configure wave -timelineunits us
- #----------------------------------------------------------------------
- #运行
- run 10us

按照如图方式创建modelsim_test、src、sim三个文件夹,并将FPGA设计文件和测试平台文件和自动化脚本放入如图文件夹
打开软件更改Change Directory路径为3.1.的sim文件夹
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。