1. 锁存器(Latch)
1.1锁存器是什么?
锁存器,顾名思义就是存储数据的器件,
1.2锁存器的缺点?
- 对毛刺敏感
- 占用更多的逻辑资源
- 不能异步复位
- 额外的延时
- 复杂的静态时序分析
1.3产生Latch的情况:
- 组合逻辑中if-else条件分支语句缺少else语句
- 组合逻辑case条件分支语句条件未列举完,同时缺失了default语句
- 组合逻辑中输出变量赋值给自己
- 在组合逻辑中多条赋值语句,每个分支条件下赋值语句的不完整
- 组合逻辑中 always@() 块内敏感列表没有列全,该触发的时候没有触发,那么相关寄存器还是会保存之前的输出结果,因而会生成锁存器。直接用 always@(*) 即可消除 latch
2. 任务(task)与函数(function)
任务和函数的区别:
比较点 | 任务 | 函数 |
---|---|---|
输入 | 任务可以没有输入或者多个输入,且端口声明可以为inout型 | 函数至少有一个输入,且端口声明不能包含inout型 |
输出 | 任务可以没有或者有多个输出 | 函数没有输出 |
返回值 | 任务没有返回值 | 函数有返回值 |
执行起始时刻 | 任务可以延时,所以可以非零时刻 | 在调用的时候立即执行 |
时序逻辑控制 | 任务中不能出现always语句,但可以包含其他时序控制,如延时语句 | 函数不能包括任何时序逻辑控制 |
调用 | 任务可以调用函数和任务 | 函数只能调用函数类型,例如automatic函数可以函数自己调用自身 |
实例化 | 任务可以作为一条单独的语句出现 | 函数调用的时候不能单独作为一条语句,必须放在赋值符号的右边。即必须有个寄存器来接受函数的返回值 |
详细请异步菜鸟教程[https://www.runoob.com/w3cnote/verilog-task.html]
2.1 函数
在verilog中如果遇到重复性的操作,可以将重复性的行为进行提取,封装成函数来避免重复代码的多次编写。
函数声明的格式:
function range[n-1:0] function_id;
input_declaration ;//输入
other_declaration ;//输出
procedural_statement ;//处理过程
endfunction
2.2 任务
2.2.1任务
任务可以在模块中的任何位置声明,并可以在任何位置使用,作用范围也仅限于该模块。
当模块内出现一下任意一个条件时,则必须使用任务而不能使用函数:
1)子程序中包含时序控制逻辑,如延迟,事件控制等
2)没有输入变量,函数是要求必须有一个输入变量的,因此当没有输入变量的时候,只能用任务。
3)没有输出或者有多个输出的时候,必须使用任务,因为函数只有返回值,没有输出。
任务声明的格式:
task task_id;
input [N-1:0] a;
input [N-1:0] b;
output c;
//逻辑实现
endtask;
任务调用格式:
task_id(input1, input2,…, output1, output2);
2.2.2 automatic 关键字
和函数一样,automatic关键字也可以用于对任务进行声明,以便当调用任务时分配的存储空间是动态的——即不同的任务实例对应的不同的存储空间。从而不影响多个相同任务并发执行。
task automatic task_id;
input [N-1:0] a;
input [N-1:0] b;
output c;
//逻辑实现
endtask;
3. 时间尺度timescale
`timescale 10ns/1ns
module test;
reg set;
parameter d=1.55;
initial begin
#d set=0;
#d set=1;
end
endmodule
观察上面的代码,说明在仿真时刻为()时,寄存器set被赋值为0;在仿真时刻为()时,寄存器set被赋值为1?
答案:16,32
因为timescale 前面是时间单位,后面是时间精度,而时间单位是10ns,所以,在test模块中,所有的时间值应为10ns的整数倍,且以1ns为时间
精度。这样经过取整操作,存在参数d中的延迟时间实际是16ns,这意味着在仿真时刻为16ns时寄存器set被赋值0;在仿真时刻为32ns时寄存器set被赋值1。
4.在配置IP核的时候选择block RAM还是 distributed RAM的选择依据
-
分布式 RAM:
- 特点:分布式 RAM 通常分布在FPGA的逻辑资源中,每个LUT(查找表)都包含少量的分布式RAM,可以用于存储小规模的数据。
- 优点:适用于存储小型数据集,对于逻辑资源的占用较小,读取延迟较低。
- 缺点:容量有限,不适合存储大量数据,不能实现大规模的数据并行处理。
-
块状 RAM:
- 特点:块状RAM通常是专门构建的存储块,可以存储大规模的数据,通常与处理器连接,支持高带宽的数据访问。
- 优点:适用于存储大型数据集,支持高速数据访问,具有较高的容量。
- 缺点:占用更多的FPGA资源,可能引入一些访问延迟,特别是在某些情况下。
-
选择分布式 RAM和块 RAM的依据:
- 数据规模:如果需要存储大量数据,块RAM通常更合适。如果只需要存储少量小数据,分布式RAM可以节省FPGA资源。
- 访问速度:块RAM通常具有更快的访问速度,适合对数据进行高速读写操作。分布式RAM的访问速度可能较慢。
- FPGA资源占用:如果FPGA资源有限,分布式RAM可能更适合,因为它不会占用太多逻辑资源。块RAM占用较多的FPGA资源。
- 数据并行性:如果需要进行大规模的数据并行处理,块RAM可以更方便地实现,因为它支持高带宽访问。
综上所述,选择分布式RAM还是块RAM取决于具体的应用需求。通常,设计中会同时使用这两种RAM类型,以便更好地平衡资源使用和性能需求。分布式RAM通常用于存储控制信号和小型数据,而块RAM用于存储大规模数据集。
5.配置异步FIFO时,Synchronization Stages的含义
在Xilinx FPGA 设备中配置异步FIFO(First-In-First-Out)时,Synchronization Stages(同步级别)是指用于在输入数据和输出数据之间进行数据同步的缓冲区阶段的数量。异步FIFO用于连接不同时钟域之间的数据传输,因为不同的时钟域可能以不同的时钟频率运行。同步级别决定了在FIFO的输入和输出之间插入多少级同步缓冲区,以确保数据的可靠传输,同时避免数据丢失或不同步。
每个同步级别对应于一个时钟周期的缓冲区。增加同步级别可以提高数据稳定性,但也会增加FIFO的延迟。同步级别的选择通常需要根据应用需求和时钟域的异步性来权衡。以下是一些关于同步级别的要点:
-
较低的同步级别:减少同步级别可以减小FIFO的延迟,但可能会增加数据不稳定性,因为输入和输出时钟域之间的差异可能无法充分缓冲。
-
较高的同步级别:增加同步级别可以提高数据稳定性,但会引入更多的延迟。如果时钟域之间的差异很大,通常需要更多的同步级别。
在Xilinx的工具中,通常可以使用FIFO Generator或者其他IP核配置工具来生成异步FIFO,并在其中指定同步级别。在生成FIFO时,您可以考虑输入和输出时钟域的频率差异、数据的带宽要求以及延迟限制,以选择适当的同步级别。