我是靠谱客的博主 背后小霸王,最近开发中收集的这篇文章主要介绍23.Verilog知识点(2),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

8.过程块

任务中不能出现 initial 语句和 always 语句语句, 但任务调用语句可以在 initial 语句和 always 语句中使用。

1)过程块有两种:
initial 块,只能执行一次
always 块,循环执行
过程块中有下列部件:
过程赋值语句:在描述过程块中的数据流
高级结构(循环,条件语句):描述块的功能
时序控制:控制块的执行及块中的语句。

2)initial语句

一个模块中可以有多个 initial 块,它们都是并行运行的。initial 块常用于测试文件和虚拟模块的编写,用来产生仿真测试信号和设置信号记录等仿真环境。

3)always语句

always 语句在仿真过程中是不断重复执行的。always 语句由于其不断重复执行的特性,只有和一定的时序控制结合在一起才有用。如果一个 always 语句没有时序控制,则这个 always 语句将会发成一个仿真死锁。见下例:

always areg = ~areg;
这个 always 语句将会生成一个 0 延迟的无限循环跳变过程,这时会发生仿真死锁。如果加
上时序控制,则这个 always 语句将变为一条非常有用的描述语句。见下例:
always #10 areg = ~areg;
这个例子生成了一个周期为 20 的无限延续的信号波形,常用这种方法来描述时钟信号,作
为激励信号来测试所设计的电路。

always 的时间控制可以是沿触发也可以是电平触发的,可以单个信号也可以多个信号,中
间需要用关键字 or 连接,如

always @(posedge clock or posedge reset) //由两个沿触发的 always 块
always @( a or b or c ) //由多个电平触发的 always 块

沿触发的 always 块常常描述时序逻辑,如果符合可综合风格要求可用综合工具自动转换为表示时序逻辑的寄存器组和门级逻辑,而电平触发的 always 块常常用来描述组合逻辑和带锁存器的组合逻辑,如果符合可综合风格要求可转换为表示组合逻辑的门级逻辑或带锁存器的组合逻辑。一个模块中可以有多个 always 块,它们都是并行运行的。

9.位宽

有符号数(补码): -2^(N-1) ~ 2^(N-1)-1,正数范围-1,是因为 0 算在正数范围中
如, N = 8,则表示范围是: -128 ~ 127

无符号数: 0~2^N-1
如, N = 8,则表示范围是: 0~255

有符号定点数:如 N = 8, 3Q5 :意思为共 8 位, 3 位整数位 5 位小数位,如果有符号,那么整数位被占去一位。所以整数部分其实只有 2 位,最大为 4。小数位有 5 位,那么最大值为:4 + ∑ 2^(-i) (i = 1…5) - 2^(-5) ;整数 + 所有小数位为 1 时的值 - 精度(最小的小数值)

为什么最大值要减 1 个精度,同样是因为 0 占掉了一个范围。最小值则为 -4 - ∑ 2^(-i) (i = 1…5)

N bit 数和 M bit 数相加、相乘后需要多少 bit?
相加相乘后需要的数据位宽,若无已知数据范围,按照基本规律:相加位宽+1,相乘位宽为 N+M(保证宽度足够)
若已知操作数范围,根据运算操作数所能表示数的绝对值最大值,求出运算结果极限值。

例如,两个 8bit 有符号数相乘,其结果需要的位宽是多少?
8bit 有符号数补码所能表示的数据范围是: -128 到 127,具有最大绝对值的数是-128,所以
极限情况下是-128*(-128) = 16384 = 2^14.
15bit 有符号数所能表示范围是: -2^14 到 2^14-1,并不能表示 2^14。综上,需要 16bit 位
宽。
正好位宽扩大一倍,也就是 8+8。

10.阻塞赋值与非阻塞赋值

阻塞赋值
阻塞赋值使用的赋值运算符为“=”。阻塞赋值的过程是立刻执行的,即阻塞赋值运算符右侧表达求值完后立刻会更新至运算符左侧,并且这个执行的过程不受其他语句执行的影响,其后的语句只有当前的赋值操作执行完成后才能顺序执行。

非阻塞赋值
非阻塞赋值使用的赋值运算符为“<=”。非阻塞赋值执行过程为:在当前仿真时间槽(timeslot)开始分析计算获得右侧表达式的值在当前时间槽执行结束时更新左侧表达式的值在右侧表达式分析计算和左侧表达式被更新之间,任何其他事件都可以执行,同时也有可能修改已经计算完成的右侧表达式的值,即非阻塞赋值的过程不影响其他语句的执行。

根据非阻塞赋值的特点,其赋值运算符左侧操作数只能为寄存器类型,因此非阻塞赋值只能用于过程性语句中(initial 和 always),不允许在连续赋值语句中使用非阻塞赋值。

阻塞:在同一个 always 块中,其后面的赋值语句从概念上是在前一条赋值语句结束后开始赋值的。

Verilog 模块编程的 8 个原则:
(1) 时序电路建模时,用非阻塞赋值。
(2) 锁存器电路建模时,用非阻塞赋值。
(3) 用 always 块建立组合逻辑模型时,用阻塞赋值。
(4) 在同一个 always 块中建立时序和组合逻辑电路时,用非阻塞赋值。
(5) 在同一个 always 块中不要既用非阻塞赋值又用阻塞赋值。
(6) 不要在一个以上的 always 块中为同一个变量赋值。
(7) 用$strobe 系统任务来显示用非阻塞赋值的变量值。
(8) 在赋值时不要使用#0 延时。

11.时间尺度

timescale 是 Verilog HDL 中的一种时间尺度预编译指令,它用来定义模块的仿真时的时间单位和时间精度。格式如下:
` timescale<时间单位>/<时间精度>

注意:用于说明仿真时间单位和时间精度的数字只能是 1、 10、 100,不能为其它的数字。
而且, **时间精度不能比时间单位还要大。最多两则一样大。
时间精度就是模块仿真时间和延时的精确程序,比如:定义时间精度为 10ns, 那么时序中所有的延时至多能精确到 10ns,而 8ns 或者 18ns 是不可能做到的。在编译过程中,timescale 指令影响这一编译器指令后面所有模块中的时延值,直至遇到另一个 timescale 指令 resetall 指令。在 verilog 中是没有默认 timescale 的,一个没有指定 timescale 的 verilog 模块就有可能错误的继承了前面编译模块的无效 timescale 参数。

12.存储器的设计

Verilog 中提供了两维数组来帮助我们建立内存的行为模型。具体来说,就是可以将内存定义为一个 reg 类型的数组,这个数组中的任何一个单元都可以通过一个下标去访问。

数组(内存)定义
reg [wordsize : 0] array_name [0 : arraysize];
例如:reg [7:0] my_memory[0:255];

其中 [7:0] 是内存的宽度(位宽),而 [0:255] 则是 内存的深度(也就是有多少存储单元),其中宽度为 8 位,深度为 256。地址 0 对应着数组中的 0 存储单元。

写操作:如果要存储一个值到某个单元中去,可以这样做:my_memory[address] = data_in;

读操作: 而如果要从某个单元读出值,可以这么做:data_out = my_memory[address];

读取内存中的某一位或者多位只需要读一位或者多个位,就要麻烦一点,因为 Verilog 不允许读/写一个位。这时,就需要使用一个变量转换一下:
例如:
data_out = my_memory[address];
data_out_it_0 = data_out[0];
这里首先从一个单元里面读出数据,然后再取出读出的数据的某一位的值。

13.三态门设计

三态指其输出既可以是一般二值逻辑电路,即正常的高电平(逻辑 1)或低电平(逻辑 0),
又可以保持特有的高阻抗状态,高阻态相当于隔断状态(电阻很大,相当于开路)。
module Tri(
input din,
input en,
output reg dout
);
always @(din or en)
if (en)
dout <= din;
else
dout <= 1'bz;
// 数据流描述
// assign dout = en ? din : 1'bz;
endmodule

14.可综合
1)verilog 可综合和不可综合语句
(1)所有综合工具都支持的结构: always, assign, begin, end, case, wire, tri, generate,aupply0, supply1, reg, integer, default, for, function, and, nand, or, nor, xor, xnor,buf, not, bufif0, bufif1, notif0, notif1, if, inout, input, instantitation, module, negedge,posedge, operators, output, parameter。
(2)所有综合工具都不支持的结构: time, defparam, $finish, fork, join, initial, delays,
UDP, wait, force。
(3)有些工具支持有些工具不支持的结构: casex, casez, wand, triand, wor, trior, real,disable, forever, arrays, memories, repeat, task, while。

2)建立可综合模型的原则

(1)不使用 initial。
(2)不使用#10。
(3)不使用循环次数不确定的循环语句,如 forever、 while 等。
(4)不使用用户自定义原语(UDP 元件)。
(5)尽量使用同步方式设计电路。
(6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。
(7)用 always 过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。

(8)所有的内部寄存器都应该能够被复位,在使用 FPGA 实现设计时,应尽量使用器件的全局复位端作为系统总的复位。
(9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。
(10)不能在一个以上的 always 过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。
(11)如果不打算把变量推导成锁存器,那么必须在 if 语句或 case 语句的所有条件分支中都对变量明确地赋值。
(12)避免混合使用上升沿和下降沿触发的触发器。
(13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。
(14)避免在 case 语句的分支项中使用 x 值或 z 值。

3)不可综合 verilog 语句
1、 initial
只能在 test bench 中使用,不能综合。(写了 initial 虽然可以通过综合,但那个不叫“能综合”)
2、 events
event 在同步 test bench 时更有用,不能综合。
3、 real
不支持 real 数据类型的综合。
4、 time
不支持 time 数据类型的综合。
5、 force 和 release
不支持 force 和 release 的综合。
6、 assign 和 deassign
不支持对 reg 数据类型的 assign 或 deassign 进行综合支持对 wire 数据类型的 assign或 deassign 进行综合。
7、 fork join
不可综合,可以使用非块语句达到同样的效果。
8、 primitives
支持门级原语的综合,不支持非门级原语的综合。
9、 table
不支持 UDP 和 table 的综合。
10、敏感列表里同时带有 posedge 和 negedge
如: always @(posedge clk or negedge clk) begin...end
这个 always 块不可综合。(如果是always@(posedge clk or negedge reset呢)

11、同一个 reg 变量被多个 always 块驱动
12、延时
以#开头的延时不可综合成硬件电路延时,综合工具会忽略所有延时代码,但不会报错。
如: a=#10 b;
这里的#10 是用于仿真时的延时,在综合的时候综合工具会忽略它。也就是说,在综合的时候上式等同于 a=b;


引用b站大佬rong晔手册










 

最后

以上就是背后小霸王为你收集整理的23.Verilog知识点(2)的全部内容,希望文章能够帮你解决23.Verilog知识点(2)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部