Verilog在编写第一行代码之前

除非你知道自己要去的地方,否则你不可能到达那里!

好的设计者一般都要对电路要实现的功能有清晰的认识,对数据流很清楚,知道数据如何从一个点移动到另-个点,这就是所谓的“勾划”(walk-through)。一旦设计蓝图在脑海中变得清晰,此后釆用Verilog编写数据路径和控制逻辑就会变得思路清晰。

脑海中的模拟

正如大多数人玩过的象棋游戏,我们都知道提前谋划是何等重要,要在下一次移动供子之前考虑好此后的几步棋应该怎么走,以确保不会出错,不被对手捕捉到机会。电路设计过程与下棋非常相似。当设计状态机、数据路径或者控制逻辑时,我们知道它们的功能。在进行设计仿真之前,我们需要思考代码在不同输入和边界条件下如何工作。如果用心去做好这一步工作,并且分析可能出现的问题,验证工作将会变得非常高效。另外,这一步也给我们建立了自信,使我们确信整个设计非常扎实,可以很好地工作。否则,很可能出现的情况足在验证阶段反复发现问题并进行电路修改,不断进行补救T.作,并且最终也不能确定设计足否还隐含着没有被发现的问题。

哪种风格—数据流或算法

描述组合逻辑有两种方式—使用wire(对应数据流描述方式)或者使用reg(对应算法描述方式)。这两种方式都能实现相同的逻辑功能,综合后得到相同的门电路,具体使用哪一种方式可以根据个人喜好。

数据流—短表达式举例

wire [7:0] regl0_nxt;
assign regl0_nxt = wren ? data_in : regl0;

算法—短表达式举例

reg [7:0] regl0_nxt;
always @(*) begin
reglO_nxt = reglO;
if (wren)
 regl0_nxt = data_in;
end

当表达式非常简单时,一般更倾向于使用数据流风格来实现,此时代码行数很少。然而,当表达式很长并且与很多条件有关时,数据流风格阅读起来较为费力。此时可以使用算法风格,可以采用if-else语句进行描述,以易于阅读和减少错误发生。

数据流-长表达式举例

wire count255_nxt;

assign count255_nxt=

enable_cnt_dn_risedge ? cut_preset_stored:
(enable_cnt_up_risedge ? ’d0:
(pause_counting ? count255:
((enable_cnt_dn && ctr_expired)? cnt_preset_stored:
(enable_cnt_dn ? (count255- l'bl):
((enable_cnt_up && ctr_expired) ? 'd0:
(enable_cnt_up ? (count255 + 1'bl): count255))))));

算法—长表达式举例

reg |7:0] count255_nxt;
always @(*) begin
 count255_nxt = count255;
 if (enable_cnt_dn_risedge)
  count255_nxt = cnt_preset_stored; // initialize to max
 else if (enable_cnt_up_risedge)  // initialize to 0
  count255_nxt = 'd0;
 else if (pause_counting)
  count255_nxt = count255;
 else if (enable_cnt_chi && ctr_expired)
  count255_nxt = cnt_preset_stored;// auto load
 else if (enable_cnt_dn)
  count255_nxt = count255 - l'bl;
 else if (enable_cnt_up && ctr_expired); // hasn’t expired
  count255_nxt = 'dO;  // auto load
 else if (enable_cnt_up)
  count255_nxt = count255 + 1’bl;// hasn’t expired

end

寄存器型输出

大型设计可被分解为很多块,每个块可进一步分解为多个模块。模块相互联接形成完整设计。模块的输出或者驱动另一个模块的输入,或者作为顶层芯片的输出引脚。在结构化和大型设计中,综合后整个电路要保持层次化结构,而不是使整个设计扁平化。当层次化得以 保留时,输出有时必须通过相对长的路径到达另一个模块,这会导致互联延时增大。为了更容易满足芯片内对建立时间的要求,内部模块应尽量采用寄存器输出,而不是组合逻辑输出,如图10.1和图10.2所示。采用寄存器输出时,可以为后续电路留下相对宽裕的布线延迟和输入组合逻辑延迟。尽量使用寄存器输出是一个非常好的设计经验。

18f881a65fda2907bb44ec818b2a09a2.png

使用状态机而不是松散的控制逻辑

状态机可以实现复杂的控制功能,它可以非常容易地将所有可能的情况和边界条件考虑进去。通过设置多个状态,并将它们相互联接可实现复杂的、重复的控制流程。如果状态机需要完成的功能很少,可以用2个或3个状态来实现。采用状态机来实现控制功能是一个好方 法,即使是只有2个或3个状态的简单状态机,都可以有效减少设计差错。

综合和仿真不匹配

在Verilog 2001岀现之前,设计者需要确定always块敏感列表中包含了所有输入信号。下面是一个例子:

always @ (in1, in2, in3) // sensitivity list
 begin
  outl = inl - in2;
  out2 = (in3 > 5) ? in1 :in2;
  end

设计者必须确保所有输入(位于表达式右边)都出现在敏感信号列表中。对于小型always块,这很简单。但是对于大型always块来说,敏感信号列表中很可能会漏项。设计者必须付出额外的努力和时间,用于查找所有输入并将它们放入敏感信号列表中。

如果某个输入从敏感信号列表中漏掉了,会发生什么情况呢?如果一个输入发生了变化,仅当它出现在敏感信号列表中时,仿真器才进入always块中执行其中的语句。如果漏掉了某个敏感信号,那么该部分电路的仿真结果与综合后的逻辑功能相比可能会有很大差别。由于Verilog 2001版标准中不再需要将这些输人放在敏感信号列表中,仿真器会自动弄清楚所有的敏感信号,综合后的结果也会与仿真结果相同。举例如下。

//Verilog 2001
always @ (*) // sensitivity list
 begin
  outl = inl - in2;
  out2 = (in3 > 5) ? in1 :in2;
end

设计的模块化和参数化

结构化设计比非结构化设计更有用。管理者和决策者可以根据结构化设计作出明智的判断。类似地,结构化或者模块化设计不仅易于理解和维护,而且有利于设计共享。某些电路单元(加法器、乘法器、CRC校验电路等)能在不同的设计中被复用,可以对一组逻辑电路使用门控时钟,冗余或者相近的电路功能可以被合并或者消除。采用模块化设计后,所有这些都可能成为现实。此外,标准电路模块还能在多个设计或一个公司内部不同部门之间共享。

加法器、减法器的有效使用

在数字系统设计中,会经常用到加法器、减法器、乘法器等,需要大量数学运算时更是如此。需要特别提醒的是,数学运算电路会占用大量的门/面积资源,此时,有效使用这些电路以降低硬件资源消耗就会非常有意义。设计者可以通过改进算法,使运算电路在不同的时 间为不同的其他内部电路提供运算服务,从而减少运算电路的数量。另一种方法是优化RTL代码,减少运算电路在具体实现时消耗的资源。下面的例子,展示了如何减少加法器/减法器的数量。

case (selx)
3'b000: calx = base;
3'b001: calx = base + 16;
3'b010: calx = base + 32; 
3'b011: calx = base + 48;
3'bl00: calx = base + 64;
3'bl0l: calx = base + 80;
3'b110: calx = base + 96;
3'blll: calx = base + 112;
endcase

上面的例子需要使用7个加法器和1个复用器。通过编写不同的RTL代码可以实现同样的功能,此时只需要1个加法器和1个复用器。

case (selx)
3'b000: base_offset = 0;
3'b00l: base_offset = 16;
3'b010: base_offset = 32;
3'b011: base_offset = 48;
3'blOO: base_offset = 64;
3'bl01: base_offset = 80;
3'bl10: base_offset = 96;
3'bl11: base_offset = 112;
endcase
assign calx = base + base_offset;

图10.3是两段代码的综合结果。

2ae3f09267ecea654e0021484b5b315c.png

需要避免的情况

不要形成组合逻辑环路

当路径中有反馈,却没有触发器这类时序元件时,有可能出现组合逻辑环路,如下图所示。对于有经验的设计者来说,模块内简单的组合逻辑环路易于发现和避免。然而,当信号由组合逻辑电路产生,穿过多个模块,最后返回到原模块所形成的组合逻辑环路却难以识別。可能直到对整个电路进行仿真时才会注意到该环路。此时,仿真器无法仿真出有效的结果或者会因为进入死循环而长时间停留在某一仿真时刻。查找组合逻辑环路的起点较为困难,采用单步仿真方式查找环路起点的工作非常烦琐且令人厌烦。采用寄存器输出的方式可以有效地减少形成组合逻辑环路的机会。

bd5ead60860c095430a452b6933385ac.png

避免意外生成锁存器

在时序电路设计中,一般会选择D触发器作为存储元件。锁存器也能存储数值,但有一些不好的特性,除非真的需要,否则不应在设计中使用它。在编写RTL代码时,如果没有遵循一定的规则,可能会出现意想不到的锁存器。

下面是一些综合后会生成锁存器的例子。生成锁存器并不是设计的初衷,因此要熟悉容易生成锁存器的代码结构并加以避免。使用always块生成组合逻辑电路时,如果变量所有可能的取值没有被考虑完全,那么综合后可能会生成锁存器,如下面代码所示。

always @ *
begin
 if (a < b)
 c = d;
end

在上面的例子中,给出了a<b条件为真时c的取值为d没有说明如果a大于b时c取什么值。综合工具会认为a大于b时c保持原来的值不变,这样综合后的电路中就会出现锁存器。为了避免产生意想不到的锁存器,可以按照如下方式编写代码。

always @ *
 begin
 if (a < b)
  c=d;
 else
  c=0;
end

一种简单的避免产生锁存器的方法是给变量赋初值,如下面代码所示。这样即使后面的代码没有覆盖所有的取值,也不会生成锁存器。

always @ *
 begin
  c = 0;
 if (a < b)
  c = d;
 end

不要采用基于延迟的设计

逻辑设计中要避免利用门延迟产生所需要的脉冲。

如下图所示的电路,该电路利用反相器的门延迟在与门输岀端产生了一个正脉冲。延迟大小取决于PVT(集成电路生产工艺、工作 电压和环境温度),这意味着延迟不是固定的,将随着工作电压、温度和制作工艺而改变。当设计被移植到更先进的工艺上生产时(例如,65~28nm集成电路工艺),脉冲宽度将减小,最终成为毛刺。因此,这样的逻辑设计不推荐使用,应该被避免。

6366a16cb6493c395cb4c47b9cd76045.png

不要对一个变量多次赋值

在Verilog中,不要在多个always块内对同一个变量赋值。综合工具将产生两个独立的逻辑块,并将它们用“线或”方式连接,从而造成设计错误。对一个变量的赋值必须在一个always块内进行,下面是一个进行对比分析的例子。

541f42dd8c6847465df3866b32002680.png

在多个always块内对同一个变量赋值可能不会报错,always块较少时也很容易发现这一问题,如下面代码所示。但当一个电路规模较大时,内部可能有多个always块,此时容易犯的错误是在一个always块可能对某个变量赋了初值,而在另一个always块中赋了实际值。应仔细检查,避免这类问题出现。

aee69d57df40e1f5cb1d133d9635538f.png

初步完成RTL代码之后

无论编写代码时有多么仔细,代码中都会出现bug,应在完成代码编写后趁热打铁,趁着对代码还熟悉及时查找问题,不要留到以后再解决。很多情况下,你并没有意识到代码中存在错误,也不是想把问题留到以后去解决,而是设计团队的其他人告诉你时,你才意识到这个代码存在设计错误。此时也许已经过了2天、2个月甚至2年,再查找问题的难度就会增大很多。

代码编写完成并进行第一遍修改后,应再一次对代码进行查看,按照你脑海中的步骤重新对设计检查一遍,这样不止会避免较为明显的错误,还可能发现隐藏较深的边界问题,这将大大提高工作效率。最为重要的是,验证工程师的工作量会减少,设计者本人也不需要花花费更多的时间来重新消化原来的设计并修改代码中的问题。总之,问题越早解决越好。

多数情况下,进行代码编写时,我们会使用剪切和粘贴来避免重复和枯燥的代码输入工作,此后再对粘贴的代码段进行修改,比如修改地址、索引等。对于这类枯燥的工作,设计者本能地会感到厌烦并且注意力不容易集中,恰恰此时最容易出现低级错误。代码编写完成 后,应对代码进行目测检查,一些简单的问题,比如代码缩进、空格和对齐等,很容易进行目测检查,也很容易找出剪切和粘贴时岀现的错误。编写完RTL代码之后,应及时目测检查一遍。

对发现bug感到惊喜

我们不会因为设计中有bug就否定设计者的成绩,而是要让设计者明白bug的确会存在,简单的bug比如拼写错误,在每个设计者身上都会发生,这在验证过程中很容易发现。然而,对于边界问题、由于没有充分理解而造成的设计错误,或者多个事件组合在一起时才会发生的错误等,在仿真期间有时也难以发现。当进行代码分析时,你可能会发现,在那么努力地进行设计和检查之后,仍然存在一些问题。此时,对问题进行深入分析有助于使设计者获得更多的设计经验从而变得更加成熟,并在以后的设计中避免类似的问题。

设计要面向未来使用需求

典型的芯片或电路内部都有映射在处理器存储空间中的寄存器,驱动程序可以对寄存器进行配置或者通过读取状态寄存器的值得到电路的工作状态。进行寄存器定义时,建议将功能相同的比特位单独分组并编址,不要将功能不同的寄存器合并在一起编址。例如,要定义3个状态位和3个控制位,不要将它们放在一个字节中,应将3个状态位放到一个字节屮(剩下的5比特作为保留位),将3个控制位放到另一个字节中,这样,状态位和控制位就被编入不同的字节中,具有不同的内存映射地址。另外应将粘滞位(sticky bit)和常规比特位 (regular bit)放在不同的字节中,因为粘滞位需要单独的电源供电。在电路中恰当地设置寄存器并进行合理的编址,会简化硬件电路和驱动程序的设计。

另外,进行电路设计时要考虑到今后的设计需求。在电路架构设计时,即使已经做了充分的考虑,也可能会进行设计修改。例如,目前所需的编码数值为6,使用了一个3位寄存器,考虑到将来的需求,可以选择4位寄存器,以便于今后增大编码数值。另外,应确保重要的比特位或寄存器可以被软件访问,虽然这会增加硬件资源消耗,但是如果不这样做该数值就不能被软件读取,这会给调试带来不便。

c563498ff7bf182d37d16fc012de5d2b.gif

NOW

学习Xilinx FPGA最好的资料其实就是官方手册,下表总结了部分手册的主要介绍内容,关注我,持续更新中......

文件名主标题内容简单介绍是否有中文版
UG4767 Series FPGAs GTX/GTH  TransceiversGTX和GTH介绍,PCIe、serdes等学习必备
UG4717 Series FPGAs SelectIO Resources描述 7 系列 FPGA 中可用的 SelectIO资源。
UG1114PetaLinux Tools DocumentatonPetaLinux 工具文档 参考指南是,V2019.2
UG949UltraFAST 设计方法指南(适用于 Vivado  Design Suite)赛灵思® UltraFast™  设计方法是用于为当今器件优化设计进程的一套最佳实践。这些设计的规模与复杂性需要执行特定的步骤与设计任务,从而确保设计每一个阶段的成功开展。依照这些步骤,并遵循最佳实践,将帮助您以最快的速度和最高的效率实现期望的设计目标是,V2018.1
IP手册pg057FIFO GeneratorFIFO生成器IP使用手册
pg104Complex Multiplier复数乘法器IP使用手册
pg122RAM-Based Shift Register 移位寄存器IP使用手册

25802499c081657c12a5aa3c5354fd0a.png

推荐阅读

【Vivado那些事】如何查找官网例程及如何使用官网例程

【Vivado使用误区与进阶】总结篇

【Vivado那些事】Vivado中常用的快捷键(二)其他常用快捷键

SystemVerilog数字系统设计_夏宇闻 PDF

图书推荐|ARM Cortex-M0 全可编程SoC原理及实现

简谈:如何学习FPGA

1202年了,还在使用虚拟机吗?Win10安装Ubuntu子系统及图形化界面详细教程

Github 上有哪些优秀的 VHDL/Verilog/FPGA 项目

AD936x+ZYNQ搭建收音机(一)

AD936x+ZYNQ搭建OpenWIFI

无招胜有招-Vivado非工程模式下的详细设计

面试中经常会遇到的FPGA基本概念,你会几个?

Vivado ML(机器学习) 2021尝鲜

推荐一些可以获取免费的国外的原版书籍(电子版)网站

【Vivado那些事】FPGA的配置方式

FPGA 的重构

浅析FPGA局部动态可重构技术

ISP(图像信号处理)算法概述、工作原理、架构、处理流程

国产CPU概括

从电子游戏历史看IC发展的助推剂

80年代电子游戏及电脑游戏的发展历史

PCIe总线的基础知识

万字长文带你回顾电子游戏的七十多年历史(完整版)

FPGA中异步复位,同步释放的理解

OpenFPGA系列文章总结

用Verilog设计一个16 位 RISC 处理器

介绍一些新手入门FPGA的优秀网站(新增)

Verilog数字系统基础设计-CR

Verilog数字系统基础设计-奇偶校验

建立和保持时间及时序简单理解

(Xilinx)FPGA中LVDS差分高速传输的实现

Xilinx Multiboot实例演示

高速串行通信常用的编码方式-8b/10b编码/解码
Verilog计时(微秒、毫秒和秒)脉冲的产生及同步整形电路

再说System Verilog 与 Verilog 的关系

图书推荐|一本图像/视频处理的强大工具书

Verilog HDL-同步技术

再说System Verilog 与 Verilog 的关系

数模混合信号建模语言Verilog-AMS

【Vivado那些事儿】强制修改打开Vivado工程使用的Vivado版本

Intel/Altera 系列FPGA简介

一块带给无数人年少欢乐的CPU,别说你没用过它

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OpenFPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值