循环表达式
35.下列说法错误的是()
【A】为了避免wire信号出现X态,最好在声明时赋初始值0
【B】一个模块例化多次,可以使用generate for循环减少代码量
【C】模块例化时,需要将端口显式列出,即使某个端口未连接信号
【D】循环表达式的循环次数必须为常数
解析:循环表达式的循环次数必须为常数、变量或者表达式!所以D错误。A选项,为了避免wire信号出现X态,最好在声明时赋初始值0,没有见过这种说法(但也没有找到证明它错误的权威的解析),但是wire型信号是可以在声明时赋初始值0的,例如:wire a=1’b0;B选项和C选项正确。
正确答案:D
是否可以综合
31.下面的哪个语句是可以综合的()
【A】initial 过程块
【B】forever 循环语句
【C】for 循环语句
【D】fork join
解析:for语句是可以综合的,但一般会很少使用,主要原因是for循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,每条执行语句并不能有效地复用硬件逻辑资源,造成巨大的资源浪费。initial、forever、fork join语句均不能综合,一般用在Testbench中。
正确答案:C
关于除法运算的可综合性参考以下小米数字IC笔试题:
12、哪些Verilog的写法是不能综合的()
A、输入为变量的除法
B、循环边界未指定的for循环
C、含有时序电路的function函数
D、输入为变量的乘法
解析:ABC。除法不可综合。除法器在FPGA里怎么实现呢?当然不是让用“/”和“%”实现。在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。并且多数综合工具对于除运算指令不能综合出令人满意的结果,有些甚至不能给予综合。即使可以综合,也需要比较多的资源。对于这种情况,一般使用相应的算法来实现除法,分为两类,基于减法操作和基于乘法操作的算法。
verilog中可综合语句:
input、output、parameter、reg、wire、always、assign、begin..end、case、posedge、negedge、or、and、default、if、function、generate、integer、`define,while、repeat 、for (while、repeat循环可综合时,要具有明确的循环表达式和循环条件,for可综合时也要有具体的循环范围)
task和function都是可综合的,不过综合出来的都是组合逻辑电路。要想可综合,task和function内部必须是组合逻辑。
循环语句(repeat、while、for)也可以用于可综合电路设计,当采用循环语句进行计算和赋值操作时,可以综合得到逻辑电路
不可综合语句:
- initial、forever、fork join语句 wait、time、real、display。
- 避免混合使用上升沿和下降沿触发的触发器: 如:always @(posedge clk or negedge clk) begin...end,这个always块不可综合。
- 输入为变量的除法:除法不可综合,在Verilog HDL语言中虽然有除的运算指令,但是除运算符中的除数必须是2的幂,因此无法实现除数为任意整数的除法,很大程度上限制了它的使用领域。
- 循环边界未指定的for循环
- 含有时序电路的function函数:要想可综合,task和function内部必须是组合逻辑。
优先级
动态位宽截取
下列关于Verilog动态位宽截取的说法错误的是( )
A:vect_testa[4+:3]表示,截取宽度为3,升序截取
B:vect[base+:width]或[base-:width]中,width可变,base必须为常量
C:Verilog的数据截取可采用[ ]或者{ }
D:vect_testb[4-:3] = vect_testb [6:4]
官方解析:
Verilog动态固定宽度截取,vect[base±:width],base表示起始位,width表示截取宽度,base可变,width必须为常量。
截取使用方括号[],拼接使用大括号{}。
vect[base+:width]表示升序截取,vect[base-:width]表示降序截取。
选项D,vect_testb[4-:3] = vect_testb [4:2]
正确答案:BCD
其中+:表示升序,-:表示降序
vect[base±:width],base表示起始位,width表示截取宽度,base可变,width必须为常量。
截取使用方括号[],拼接使用大括号{}。
- Plain Text
- C++
- Java
- C
- Python2
- Python3
- Pypy2
- Pypy3
- JavaScript
- PHP
- C#
- R
- Go
- Ruby
- Rust
- Bash
- Shell
- CSS
- HTML
- XML
- ASP/VB
- Perl
- Swift
- Objective-C
- Pascal
- MATLAB
- Scala
- Kotlin
- Groovy
- Typescript
- SQL
- MySQL
- Oracle
- SQLite
- Scheme
- TCL
复制
删除
xxxxxxxxxx
2
1
vect_1[4+:3]表示,起始位为4,宽度为3,**升序**,则vect_1[4+:3] = vect_1[6:4]
2
vect_1[4-:3]表示,起始位为4,宽度为3,**降序**,则vect_1[4-:3] = vect_1[4:2]
Verilog 的标识符
标识符(identifier)用于定义模块名、端口名和信号名等。
- Verilog 的标识符可以是任意一组字母、数字、$和_(下划线)符号的组合,
- 但标识符的第一个字符必须是字母或者下划线。
- 另外,标识符是区分大小写的。以下是标识符的几个例子:
Count
COUNT //与 Count 不同。
R56_68
FIVE$
虽然标识符写法很多,但是要简洁、清晰、易懂,推荐写法如下:
count
fifo_w
不建议大小写混合使用,普通内部信号建议全部小写,参数定义建议大写,另外信号命名最好体现信
号的含义。
generate for循环语句
1)使用场景
当同一模块需要多次例化,或同一赋值语句需要多次执行时使用。
(2)语法
- Plain Text
- C++
- Java
- C
- Python2
- Python3
- Pypy2
- Pypy3
- JavaScript
- PHP
- C#
- R
- Go
- Ruby
- Rust
- Bash
- Shell
- CSS
- HTML
- XML
- ASP/VB
- Perl
- Swift
- Objective-C
- Pascal
- MATLAB
- Scala
- Kotlin
- Groovy
- Typescript
- SQL
- MySQL
- Oracle
- SQLite
- Scheme
- TCL
复制
删除
xxxxxxxxxx
6
1
genvar i;
2
generate
3
for(i;i<=10;i=i+1)begin:名字
4
循环执行代码;
5
end
6
endgenerate
说明:
( A )需要定义循环索引,关键字为genvar,索引名字任意取(这里举例用i)。索引可以定义在generate结构的内部或者generate结构的外部,这就决定了索引的作用范围,当定义在generate外部可以被多个generate使用,但是为了避免冲突,最好一个generate定义一个索引;
( B )generate for结构主体以generate 关键字开始,以endgenerate关键字结束;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1)**,只能是常量(genvar、parameter或lacalparam)类型,保证只会生成一种电路;
比如:我们想将循环次数10修改为一个参数:(i;i<=b;i=i+1) ,要求所有的参数i和b都是genvar,parameter或者lacalparam类型;
( D )循环的主体,在begin后最好命一个名字,如果不写这个名字,有的编译器会报警告;
(3)注意事项
(A)generate-for循环必须使用genvar关键字定义循环变量;i必须是genvar,其他的必须是常量(genvar、parameter或lacalparam)类型
(B)generate-for循环中的内容必须使用begin-end包括起来,哪怕只有一句;begin-end不可少
(C)generate-for循环begin后的名字不可以省略; begin后名字不可少
(D)generate-for循环同一个模块内的begin-end块名字不能一样。 begin后名字不重复
原文链接:https://blog.csdn.net/weixin_47730622/article/details/132742669
函数(function)与任务(task)
函数
- 函数不能单独作为一条语句出现,只能放在赋值语言的右端
- 函数的定义不能包含有任何的时间控制语句,即任何用#、@或wait来标识的语句;
- 在函数定义中必须有一条赋值语句给函数中的一个内部变量附以函数的结果值,该内部变量具有和函数名相同的名字。
- 函数只有一个返回值,且没有输出
任务
- 但Task中不能出现initial和always块,因此一般事件控制就没办法在task中使用。task中不能包含always,但是能包含forever等其他延时语句
CPLD与FPGA
case、casex、casez
下表给出case、casex、casez的真值表:
- 在case语句中,敏感表达式中与各项值之间的比较是一种全等比较,每一位都相同才认为匹配。
- 在casez语句中,如果分支表达式某些位的值为高阻z,那么对这些位的比较就会忽略,不予考虑,而只关注其他位的比较结果。
- 在casex语句中,则把这种处理方式进一步扩展到对x的处理,即如果比较双方有一方的某些位的值是z或x,那么这些位的比较就不予考虑。
- case语句是要严格对比 casez是无视z的位 casex是无视z与x的位
原文链接:https://blog.csdn.net/vivid117/article/details/102611051
无损定点化
静态时序分析STA
STA 的时序路径
STA 四种时序路径:
- 路径1:输入端口到寄存器的数据输入 D,
- 路径2:内部寄存器的时钟输入端到下一个寄存器的数据输入 D,
- 路径3:内部寄存器的时钟输入端到输出端口;
- 路径4:输入端口到输出端口。
每条时序路径包含 1 个起点和 1 个终点,
起点只能是设计的基本输入端口或内部寄存器的时钟输入端,
终点只能是内部寄存器的数据输入端或设计的基本输出端口。
STA功能
文本
链接
确认
$ https://cloud.tencent.com/developer/article/1828388$
- (1) 静态时序分析是一种验证数字集成电路时序是否合格的验证方法;
- (2) 静态时序分析的前提是同步逻辑设计(重要!),不能分析异步电路;
- (3) 静态时序分析工具计算路径延迟的总和,并比较相对于预定义时钟的延迟;
- (4) 静态时序分析仅关注时序间的相对关系,而不是评估逻辑功能;
- (5) 静态时序分析对所有的时序路径进行错误分析,不需要使用测试向量激活某个路径(与时序仿真的不同点),分析速度比时序仿真工具快几个数量级,克服了动态时序验证的缺陷,适合大规模的电路设计验证,在同步逻辑情况下,能够达到100%的时序路径覆盖;
- (6) 静态时序分析的目的是找到隐藏的时序问题,根据时序分析结果优化逻辑或者约束条件,使设计达到时序闭合(Timing Closure);
- (7) 静态时序分析能够识别的时序故障:建立时间(Setup)/保持时间(Hold)/恢复时间(Recovery)/移除时间(Removal)检查;最小跳变和最大跳变;时钟脉冲宽度、时钟畸变(Skew、Jitter);总线竞争;不受约束的逻辑通道;关键路径;约束冲突等;
STA :时序路径覆盖率 100%,穷尽所有时序路径,验证时序;
形式验证:验证功能;
$random的一般用法
$random可以产生一个有符号的32bit随机整数,一般的用法为:
1、$random %b,其中b>0。它给出了一个范围在(-b+1):(b-1)中的随机数。
2、{$random} %b,其中b>0。它给出了一个范围在0:(b-1)中的随机数。
例如:
rand = $random%60; 上述例子是产生-59-59之间的随机数;
rand = {$random}%60; 上述例子是产生0-59之间的随机数;
$finish的用法
系统任务$finish的作用是退出仿真器,结束仿真过程。格式:
$finish(n) 当$finish带参数时,根据不同的参数值,系统输出的特征信息:
- 0:不输出任何信息;
- 1:输出当前仿真时刻和位置;
- 2:输出当前仿真时刻、位置和仿真过程中所用的memory及CPU时间的统计。
- 当$finish后面不带参数时,则默认参数为1。
$stop的用法
$stop任务得作用是把EDA工具(例如仿真器)置为暂停模式,在仿真环境下给出一个交互式的命令提示符,将控制权交给用户。格式与$finish类似:
- $stop
- $stop(n)
用法同样与$finish类似:当$stop带参数时,如(2),根据不同的参数值,系统输出的特征信息:
- 0:不输出任何信息;
- 1:输出当前仿真时刻和位置;
- 2:输出当前仿真时刻、位置和仿真过程中所用的memory及CPU时间的统计。
- 当$stop后面不带参数时,则默认参数为1。
testbench
- testbench中,输入为reg,输出为wire
- 在always块内部的变量输出,可以用wire型变量
数据有几位
注意:2’hFF = 11:这个2’指的是2bit数据
写文件的命令
- $fmonitor、$fstrobe、$fdisplay、$fwrite都是用来写文件的。
- $dumpfile的作用是选择VCD文件的名称。不是写是导入,将已经生成的波形仿真文件导入到VCD中,而写文件是的是我把自己想写的任意数据写下来。
$display的用法
- %0表示用最少位数表示
$ https://www.runoob.com/w3cnote/verilog2-display.html$
关键词:$display, $write, $strobe, $monitor
$strobe
$strobe 为选通显示任务。$strobe 使用方法与 $display 一致,但打印信息的时间和 $display 有所差异(也可以直接打印文本)。
当许多语句与 $display 任务在同一时间内执行时,这些语句和 $display 的执行顺序是不确定的,一般按照程序的顺序结构执行。两者的区别在于:$strobe命令会在当前时间部结束时完成;而$display是只要仿真器看到就会立即执行。
$strobe 是在其他语句执行完毕之后,才执行显示任务。例如:
这是因为该语句: a <= a + 1 ;也就是说a的第二次赋值是非阻塞赋值,而非阻塞赋值是需要时间的。
在第一次打印时,$display不会管你a是阻塞赋值还是非阻塞赋值,它就直接打印a当前的值1。而$strobe则会等到非阻塞赋值完成后再打印,所以其打印的值为2。
在第二次打印时,又延时了1ns,所以此时的非阻塞赋值完成,那么$strobe与$display的打印内容就均为2了。
$monitor
$monitor 为监测任务,用于变量的持续监测。只要变量发生了变化,$monitor 就会打印显示出对应的信息。 其使用方法与 $display一致。