
目录
VCS 是Synopsys公司的EDA软件,主要用于Verilog 的逻辑仿真。这里记录一下学习的过程。软件的安装可以参考下面的链接:
Synopsys EDA Tools 安装问题记录
https://blog.csdn.net/qq_43045275/article/details/127630241软件的学习参考了如下的链接:
本系列的文章对此做一个整理,结合虚拟机内的的VCS工具进行实践。
OS:Ubuntu 16.04
EDA Tool :Vcs2016
支持语言:Verilog HDL、VHDL、System Verilog、PLI(可编程语言接口)
PLI可以支持对C、C++、语言的编译仿真。


1、Vcs读取所有的initial块、always块、连续赋值语句 assign等;
2、首先执行无延迟语句,如寄存器初始化;
3、将仿真时间设为 0 ;
4、进入 active 区域,首先执行原语,即UDP(用户自定义原语,如基本的逻辑门、CMOS、PMOS逻辑、上下拉);然后执行显示 display(是一个系统任务);然后执行assign连续赋值语句(无延迟);而后是阻塞赋值语句,即always块内部的组合逻辑 “=”;
最后是非阻塞赋值(always块的时序逻辑“<=”)右边表达式的计算。
5、进入 inactive 区域,此处主要处理 #0 延迟。
6、进入非阻塞赋值(Nonblocking assign)区域。
7、进入 monitor 区域,可以监测到非阻塞赋值的新值。
8、进入 future 区域,处理其他逻辑。

准备:
1、在工程路径下面创建该文件:
2、代码:
`timescale 1ns/1ps `define CASE1 module TEST; reg clk,a,z,zin; always @ (posedge clk) begin a = 1'b1; #0 a = 1'b0; end `ifdef CASE1 always @ (a) #0 z=zin; always @ (a) zin=a; `else always @ (a) z = zin; always @ (a) #0 zin = a; `endif initial begin #50 clk = 1'bz; #50 clk = 1'b0; #50 clk = 1'b1; #50 $finish; end endmodule
操作:
1、在创建 .v 仿真文件所在的文件夹,右键打开终端。
2、输入命令:
vcs +v2k TEST.v其中 TEST.v 为文件名。
完成界面:
3、按照视频中的步骤,此时应用下面命令直接打开 DVE:
./simv -gui但是,我这边始终报错:
按照错误的指示,我重新编译仿真文件,并且加入要求的选项:
完成后,用上面的命令再次尝试,可以直接打开DVE
4、添加波形界面:
5、开始仿真
6、仿真结果
但是我此处的结果和视频中的不一致。猜测是VCS版本不同。
7、退出
数字IC设计必备技能:
1、基础的数字IC设计知识,数电等;
2、熟悉linnux 或 Unix操作系统;
3、熟练使用文本编辑器 VI 或VIM;
主要分为2步:
1、编译(将源代码转换为二进制可执行文件 simv)
2、仿真

PLI,程序语言接口,可以支持在HDL语言中调用 C、C++程序
多抽象级:行为级、RTL级、门级










由于视频作者并没有公布源码,所以这里演示实践的时候,我自己随便写一个设计文件(简单状态机)和一个仿真文件。源代码给出:
用状态机写一个计数器:
当抓取到开始信号的上升沿后,开始计数并且输出有效信号拉高。计数到计数器全1时,结束计数,返回IDLE状态。
- // |--------------------------------- VCS test design file ---------------------------------
- // |Description : a simple fsm.
- // |Author : Xu Y. B.
- // |Date : 2022-11-06
- // |
- // |----------------------------------------------------------------------------------------
-
-
- `timescale 1ns/1ns
-
- module FSM #(
- // --------------module parameters specify ----------------
- parameter P_DATA_WIDTH = 10
-
- )(
- // --------------input / output ports specify--------------
- // input ports
- input I_CLK_100M,
- input I_RSTN,
- input I_FSM_START,
- // output ports
- output reg O_DATA_VAL,
- output reg [P_DATA_WIDTH-1:0] O_DATA
- );
- // --------------module internal parameters----------------
- localparam LP_ST_IDLE = 2'b01;
- localparam LP_ST_COUNT = 2'b10;
- // --------------module internal signals-------------------
- reg [1:0] R_STATE;
- reg [1:0] R_I_FSM_START;
- wire W_I_FSM_START_PDG;
- // --------------module logic------------------------------
- // grab the posedge of input signal I_FSM_START
- always @ (posedge I_CLK_100M)
- begin
- if(~I_RSTN)
- begin
- R_I_FSM_START <= 2'b00;
- end
- else
- begin
- R_I_FSM_START[0] <= I_FSM_START;
- R_I_FSM_START[1] <= R_I_FSM_START[0];
- end
- end
- assign W_I_FSM_START_PDG = R_I_FSM_START[0] & (~R_I_FSM_START[1]);
- always @ (posedge I_CLK_100M)
- begin
- if(~I_RSTN)
- begin
- R_STATE <= LP_ST_IDLE;
- O_DATA_VAL <= 1'b0;
- O_DATA <= {P_DATA_WIDTH{1'b0}};
- end
- else
- begin
- case(R_STATE)
- LP_ST_IDLE:
- begin
- O_DATA_VAL <= 1'b0;
- O_DATA <= {P_DATA_WIDTH{1'b0}};
-
- if(W_I_FSM_START_PDG)
- begin
- R_STATE <= LP_ST_COUNT;
- end
- else
- begin
- R_STATE <= R_STATE;
- end
- end
- LP_ST_COUNT:
- begin
- if(&O_DATA)
- begin
- O_DATA_VAL <= 1'b0;
- O_DATA <= {P_DATA_WIDTH{1'b0}};
- R_STATE <= LP_ST_IDLE;
- end
- else
- begin
- O_DATA_VAL <= 1'b1;
- O_DATA <= O_DATA + 1;
- R_STATE <= LP_ST_COUNT;
- end
- end
- default:
- begin
- R_STATE <= LP_ST_IDLE;
- end
- endcase
- end
- end
- endmodule
- // |--------------------------------- VCS test testbench file -------------------------------
- // |Description : a simple fsm testbench.
- // |Author : Xu Y. B.
- // |Date : 2022-11-06
- // |
- // |----------------------------------------------------------------------------------------
-
-
- `timescale 1ns/1ns
- module TB();
- // --------------module parameters specify ----------------
- parameter P_DATA_WIDTH = 10;
-
- // --------------input / output ports specify--------------
- // input ports
- reg I_CLK_100M;
- reg I_RSTN;
- reg I_FSM_START;
- // output ports
- wire O_DATA_VAL;
- wire [P_DATA_WIDTH-1:0] O_DATA;
-
- // --------------clock setting-----------------------------
- `define CLK_PRD 10
- initial I_CLK_100M = 1'b0;
- always #(`CLK_PRD/2) I_CLK_100M = ~I_CLK_100M;
-
- // --------------control signals setting-------------------
- initial
- begin
- I_RSTN = 1'b0;
- I_FSM_START = 1'b0;
- #(`CLK_PRD*10);
- I_RSTN = 1'b1;
- #(`CLK_PRD*5);
- I_FSM_START = 1'b1;
- @(negedge O_DATA_VAL);
- #(`CLK_PRD*10);
- $finish;
- end
-
- // --------------initiate module---------------------------
- FSM #(
- .P_DATA_WIDTH(P_DATA_WIDTH)
- ) FSM_INST (
- .I_CLK_100M (I_CLK_100M),
- .I_RSTN (I_RSTN),
- .I_FSM_START (I_FSM_START),
- .O_DATA_VAL (O_DATA_VAL),
- .O_DATA (O_DATA)
- );
-
- endmodule
之前用惯了sublime text3写代码,于是就将sublime text3 搬到Linux系统下,具体方法:
1、较为简单:
2、较为详细:
安装完成后,直接在终端输入 subl 即可打开。
关闭更新提醒:关闭sublime更新提示
打开后图形操作界面以及方法和Windows下相同。
Ubuntu16.4 使用中文输入法:
记得,虚拟机开机后,重新运行 lmg-scl,后面考虑将其放在启动文件内。

编译结束后执行仿真:

添加信号进行波形仿真:


状态信号可以显示其状态名:

这里做一个对比,连续两次对源代码文件(未作修改)作增量编译,第二次就会有如下提示:







宏的定义:
由于我展示的实际文件没有宏定义,所以这里仅做方法介绍。
创建一个头文件,里面定义一个 NOTHING 的宏:
1、在源代码里定义;
2、通过 +define 选项指定;
3、通过头文件的形式;
-1- 在源文件中包含头文件;
-2-编译时增加包含的路径:
欢迎交流~~~~~~~