verilog大牛经验总结
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
我们先来看开关时延,这个时延是由器件物理特性决定的,我们没有办法去改变,所以我 们只能通过改变走线方式和减少组合逻辑的方法来提高工作频率。
1.通过改变走线的方式减少时延。 以 Altera 的器件为例,我们在 quartus 里面的 timing closure floorplan 可以看到有很 多条条块块,我们可以将条条块块按行和按列分,每一个条块代表 1 个 LAB,每个 LAB 里有 8 个或者是 10 个 LE。它们的走线时延的关系如下:同一个 LAB 中(最快) < 同列或者同行 < 不同行且不同列。
s1:
a <= 1'b0; //由于上面赋了默认值,这里就不用再对 b、c 赋 值了(b、c 在该状态为 0,不会产生锁存器,下同)
s2: b <= 1'b1;
s3: c <= 1'b1;
default: ... ...
3.ALTERA 参考设计准则 1) Ensure Clock, Preset, and Clear configurations are free of glitch es. 2) Never use Clocks consisting of more than one level of combinatori al logic. 3) Carefully calculate setup times and hold times for multi-Clock sy stems. 4) Synchronize signals between flipflops in multi-Clock systems when the setup and hold time requirements cannot be met. 5) Ensure that Preset and Clear signals do not contain race conditio ns. 6) Ensure that no other internal race conditions exist. 7) Register all glitch-sensitive outputs. Synchronize all asynchronous inputs. 9) Never rely on delay chains for pin-to-pin or internal delays. 10)Do not rely on Power-On Reset. Use a master Reset pin to clear al l flipflops. 11)Remove any stuck states from state machines or synchronous logic.
8)所有模块的输出都要寄存器化,以提高工作频率,这对设计做到时序收敛也是极有
好处的。
9) 除非是低功耗设计,不然不要用门控时钟--这会增加设计的不稳定性,在要用到门
控时钟的地方,也要将门控信号用时钟的下降沿打一拍再输出与时钟相与。
clk_gate_en
--------
----
-----------------|D Q |------------------| \ gate_clk_out
据说是大牛一总结
规范很重要
工作过的朋友肯定知道,公司里是很强调规范的,特别是对于大的设计(无论软件还是 硬件),不按照规范走几乎是不可实现的。逻辑设计也是这样:如果不按规范做的话,过一 个月后调试时发现有错,回头再看自己写的代码,估计很多信号功能都忘了,更不要说检错 了;如果一个项目做了一半一个人走了,接班的估计得从头开始设计;如果需要在原来的版 本基础上增加新功能,很可能也得从头来过,很难做到设计的可重用性。在逻辑方面,我觉 得比较重要的规范有这些:
wren,
rden,
avalon_din, //related to avalon bus
sdi,
//related to serial port input
//output
data_ready,
avalon_dout, //related to avalon bus
...
); 4) 一个模块尽量只用一个时钟,这里的一个模块是指一个 module 或者是一个 entity。 在多时钟域的设计中涉及到跨时钟域的设计中最好有专门一个模块做时钟域的隔离。这样做 可以让综合器综合出更优的结果。 5) 尽量在底层模块上做逻辑,在高层尽量做例化,顶层模块只能做例化,禁止出现任 何胶连逻辑(glue logic),哪怕仅仅是对某个信号取反。理由同上。 6) 在 FPGA 的设计上禁止用纯组合逻辑产生 latch,带 D 触发器的 latch 的是允许的, 比如配置寄存器就是这种类型。 7) 一般来说,进入 FPGA 的信号必须先同步,以提高系统工作频率(板级)。
begin
...
else if ( rs232_1xclk == 1'b1 )
...
end
11)状态机要写成 3 段式的(这是最标准的写法),即
...
always @(posedge clk or negedge rst_n)
...
current_state <= next_state;
...
always @ (current_state ...)
其它方面的规范一时没有想到,想到了再写,也欢迎大家补充。 ============================================================================== ==============================================================================
1.设计必须文档化。要将设计思路,详细实现等写入文档,然后经过严格评审通过后才能 进行下一步的工作。这样做乍看起来很花时间,但是从整个项目过程来看,绝对要比一上来 就写代码要节约时间,且这种做法可以使项目处于可控、可实现的状态。
2.代码规范。 a.设计要参数化。比如一开始的设计时钟周期是 30ns,复位周期是 5 个时钟周期,我们 可以这么写:
parameter CLK_PERIOD = 30; parameter RST_MUL_TIME = 5; parameter RST_TIME = RST_MUL_TIME * CLK_PERIOD; ... rst_n = 1'b0; # RST_TIME rst_n = 1'b1; ... # CLK_PERIOD/2 clk <= ~clk; 如果在另一个设计中的时钟是 40ns,复位周期不变,我们只需对 CLK_PERIOD 进行重新 例化就行了,从而使得代码更加易于重用。
我们先来分析下是什么影响了电路的工作频率。
我们电路的工作频率主要与寄存器到寄存器之间的信号传播时延及 clock skew 有关。 在 FPGA 内部如果时钟走长线的话,clock skew 很小,基本上可以忽略, 在这里为了简单起 见,我们只考虑信号的传播时延的因素。 信号的传播时延包括寄存器的开关时延、走线时延、 经过组合逻辑的时延(这样划分或许不是很准确,不过对分析问题来说应该是没有可以的), 要提高电路的工作频率,我们就要在这三个时延中做文章,使其尽可能的小。
由于做到这一点,在编码的时候自然就很快了,最重要的是这样做后可以让设计会一直 处于可控的状态,不会因为某一处的错误引起整个设计从头进行。 如何提高电路工作频率
对于设计者来说,我们当然希望我们设计的电路的工作频率(在这里如无特别说明,工 作频率指 FPGA 片内的工作频率)尽量高。我们也经常听说用资源换速度,用流水的方式可以 提高工作频率,这确实是一个很重要的方法,今天我想进一步去分析该如何提高电路的工作 频率。
来自百度文库
...
case(current_state)
...
s1:if ...
next_state = s2;
...
...
always @(posedge clk or negedge rst_n)
...
else
a <= 1'b0;
c <= 1'b0;
c <= 1'b0;
//赋默认值
case(current_state)
|
|
---------|
)---------
------o|>
|
|
|/
clk |
--------
|
----
------------------------------------
10)禁止用计数器分频后的信号做其它模块的时钟,而要用改成时钟使能的方式,否则
这种时钟满天飞的方式对设计的可靠性极为不利,也大大增加了静态时序分析的复杂性。如
时序是设计出来的
我的 boss 有在华为及峻龙工作的背景,自然就给我们讲了一些华为及 altera 做逻辑的一 些东西,而我们的项目规范,也基本上是按华为的那一套去做。在工作这几个月中,给我感 触最深的是华为的那句话:时序是设计出来的,不是仿出来的,更不是湊出来的。 在我们 公司,每一个项目都有很严格的评审,只有评审通过了,才能做下一步的工作。以做逻辑为 例,并不是一上来就开始写代码,而是要先写总体设计方案和逻辑详细设计方案,要等这些 方案评审通过,认为可行了,才能进行编码,一般来说这部分工作所占的时间要远大于编码 的时间。 总体方案主要是涉及模块划分,一级模块和二级模块的接口信号和时序(我们要 求把接口信号的时序波形描述出来)以及将来如何测试设计。在这一级方案中,要保证在今 后的设计中时序要收敛到一级模块(最后是在二级模块中)。什么意思呢?我们在做详细设 计的时候,对于一些信号的时序肯定会做一些调整的,但是这种时序的调整最多只能波及到 本一级模块,而不能影响到整个设计。记得以前在学校做设计的时候,由于不懂得设计时序, 经常因为有一处信号的时序不满足,结果不得不将其它模块信号的时序也改一下,搞得人很 郁闷。 在逻辑详细设计方案这一级的时候,我们已经将各级模块的接口时序都设计出来了, 各级模块内部是怎么实现的也基本上确定下来了。
2.通过减少组合逻辑的减少时延。 上面我们讲了可以通过加约束来提高工作频率,但是我们在做设计之初可万万不可将提高 工作频率的美好愿望寄托在加约束上,我们要通过合理的设计去避免出现大的组合逻辑,从 而提高电路的工作频率,这才能增强设计的可移植性,才可以使得我们的设计在移植到另一 同等速度级别的芯片时还能使用。
我们通过给综合器加适当的约束(不可贪心,一般以加 5%裕量较为合适,比如电路工 作在 100Mhz,则加约束加到 105Mhz 就可以了,贪心效果反而不好,且极大增加综合时间) 可以将相关的逻辑在布线时尽量布的靠近一点,从而减少走线的时延。(注:约束的实现不 完全是通过改进布局布线方式去提高工作频率,还有其它的改进措施)
我们知道,目前大部分 FPGA 都基于 4 输入 LUT 的,如果一个输出对应的判断条件大于 四输入的话就要由多个 LUT 级联才能完成,这样就引入一级组合逻辑时延,我们要减少组合 逻辑,无非就是要输入条件尽可能的少,,这样就可以级联的 LUT 更少,从而减少了组合逻 辑引起的时延。
我们平时听说的流水就是一种通过切割大的组合逻辑(在其中插入一级或多级 D 触发器, 从而使寄存器与寄存器之间的组合逻辑减少)来提高工作频率的方法。比如一个 32 位的计数 器,该计数器的进位链很长,必然会降低工作频率,我们可以将其分割成 4 位和 8 位的计数, 每当 4 位的计数器计到 15 后触发一次 8 位的计数器,这样就实现了计数器的切割,也提高了 工作频率。
b.信号命名要规范化。
1) 信号名一律小写,参数用大写。
2) 对于低电平有效的信号结尾要用_n 标记,如 rst_n。
3) 端口信号排列要统一,一个信号只占一行,最好按输入输出及从哪个模块来到哪个模
块去的关系排列,这样在后期仿真验证找错时后方便很多。如:
module a(
//input
clk,
rst_n, //globle signal
FPGA 的输入时钟是 25M 的,现在系统内部要通过 RS232 与 PC 通信,要以 rs232_1xclk 的速
率发送数据。(不明白以后研究)
不要这样做:
always (posedge rs232_1xclk or negedge rst_n)
begin
...
end
而要这样做:
always (posedge clk_25m or negedge rst_n)
1.通过改变走线的方式减少时延。 以 Altera 的器件为例,我们在 quartus 里面的 timing closure floorplan 可以看到有很 多条条块块,我们可以将条条块块按行和按列分,每一个条块代表 1 个 LAB,每个 LAB 里有 8 个或者是 10 个 LE。它们的走线时延的关系如下:同一个 LAB 中(最快) < 同列或者同行 < 不同行且不同列。
s1:
a <= 1'b0; //由于上面赋了默认值,这里就不用再对 b、c 赋 值了(b、c 在该状态为 0,不会产生锁存器,下同)
s2: b <= 1'b1;
s3: c <= 1'b1;
default: ... ...
3.ALTERA 参考设计准则 1) Ensure Clock, Preset, and Clear configurations are free of glitch es. 2) Never use Clocks consisting of more than one level of combinatori al logic. 3) Carefully calculate setup times and hold times for multi-Clock sy stems. 4) Synchronize signals between flipflops in multi-Clock systems when the setup and hold time requirements cannot be met. 5) Ensure that Preset and Clear signals do not contain race conditio ns. 6) Ensure that no other internal race conditions exist. 7) Register all glitch-sensitive outputs. Synchronize all asynchronous inputs. 9) Never rely on delay chains for pin-to-pin or internal delays. 10)Do not rely on Power-On Reset. Use a master Reset pin to clear al l flipflops. 11)Remove any stuck states from state machines or synchronous logic.
8)所有模块的输出都要寄存器化,以提高工作频率,这对设计做到时序收敛也是极有
好处的。
9) 除非是低功耗设计,不然不要用门控时钟--这会增加设计的不稳定性,在要用到门
控时钟的地方,也要将门控信号用时钟的下降沿打一拍再输出与时钟相与。
clk_gate_en
--------
----
-----------------|D Q |------------------| \ gate_clk_out
据说是大牛一总结
规范很重要
工作过的朋友肯定知道,公司里是很强调规范的,特别是对于大的设计(无论软件还是 硬件),不按照规范走几乎是不可实现的。逻辑设计也是这样:如果不按规范做的话,过一 个月后调试时发现有错,回头再看自己写的代码,估计很多信号功能都忘了,更不要说检错 了;如果一个项目做了一半一个人走了,接班的估计得从头开始设计;如果需要在原来的版 本基础上增加新功能,很可能也得从头来过,很难做到设计的可重用性。在逻辑方面,我觉 得比较重要的规范有这些:
wren,
rden,
avalon_din, //related to avalon bus
sdi,
//related to serial port input
//output
data_ready,
avalon_dout, //related to avalon bus
...
); 4) 一个模块尽量只用一个时钟,这里的一个模块是指一个 module 或者是一个 entity。 在多时钟域的设计中涉及到跨时钟域的设计中最好有专门一个模块做时钟域的隔离。这样做 可以让综合器综合出更优的结果。 5) 尽量在底层模块上做逻辑,在高层尽量做例化,顶层模块只能做例化,禁止出现任 何胶连逻辑(glue logic),哪怕仅仅是对某个信号取反。理由同上。 6) 在 FPGA 的设计上禁止用纯组合逻辑产生 latch,带 D 触发器的 latch 的是允许的, 比如配置寄存器就是这种类型。 7) 一般来说,进入 FPGA 的信号必须先同步,以提高系统工作频率(板级)。
begin
...
else if ( rs232_1xclk == 1'b1 )
...
end
11)状态机要写成 3 段式的(这是最标准的写法),即
...
always @(posedge clk or negedge rst_n)
...
current_state <= next_state;
...
always @ (current_state ...)
其它方面的规范一时没有想到,想到了再写,也欢迎大家补充。 ============================================================================== ==============================================================================
1.设计必须文档化。要将设计思路,详细实现等写入文档,然后经过严格评审通过后才能 进行下一步的工作。这样做乍看起来很花时间,但是从整个项目过程来看,绝对要比一上来 就写代码要节约时间,且这种做法可以使项目处于可控、可实现的状态。
2.代码规范。 a.设计要参数化。比如一开始的设计时钟周期是 30ns,复位周期是 5 个时钟周期,我们 可以这么写:
parameter CLK_PERIOD = 30; parameter RST_MUL_TIME = 5; parameter RST_TIME = RST_MUL_TIME * CLK_PERIOD; ... rst_n = 1'b0; # RST_TIME rst_n = 1'b1; ... # CLK_PERIOD/2 clk <= ~clk; 如果在另一个设计中的时钟是 40ns,复位周期不变,我们只需对 CLK_PERIOD 进行重新 例化就行了,从而使得代码更加易于重用。
我们先来分析下是什么影响了电路的工作频率。
我们电路的工作频率主要与寄存器到寄存器之间的信号传播时延及 clock skew 有关。 在 FPGA 内部如果时钟走长线的话,clock skew 很小,基本上可以忽略, 在这里为了简单起 见,我们只考虑信号的传播时延的因素。 信号的传播时延包括寄存器的开关时延、走线时延、 经过组合逻辑的时延(这样划分或许不是很准确,不过对分析问题来说应该是没有可以的), 要提高电路的工作频率,我们就要在这三个时延中做文章,使其尽可能的小。
由于做到这一点,在编码的时候自然就很快了,最重要的是这样做后可以让设计会一直 处于可控的状态,不会因为某一处的错误引起整个设计从头进行。 如何提高电路工作频率
对于设计者来说,我们当然希望我们设计的电路的工作频率(在这里如无特别说明,工 作频率指 FPGA 片内的工作频率)尽量高。我们也经常听说用资源换速度,用流水的方式可以 提高工作频率,这确实是一个很重要的方法,今天我想进一步去分析该如何提高电路的工作 频率。
来自百度文库
...
case(current_state)
...
s1:if ...
next_state = s2;
...
...
always @(posedge clk or negedge rst_n)
...
else
a <= 1'b0;
c <= 1'b0;
c <= 1'b0;
//赋默认值
case(current_state)
|
|
---------|
)---------
------o|>
|
|
|/
clk |
--------
|
----
------------------------------------
10)禁止用计数器分频后的信号做其它模块的时钟,而要用改成时钟使能的方式,否则
这种时钟满天飞的方式对设计的可靠性极为不利,也大大增加了静态时序分析的复杂性。如
时序是设计出来的
我的 boss 有在华为及峻龙工作的背景,自然就给我们讲了一些华为及 altera 做逻辑的一 些东西,而我们的项目规范,也基本上是按华为的那一套去做。在工作这几个月中,给我感 触最深的是华为的那句话:时序是设计出来的,不是仿出来的,更不是湊出来的。 在我们 公司,每一个项目都有很严格的评审,只有评审通过了,才能做下一步的工作。以做逻辑为 例,并不是一上来就开始写代码,而是要先写总体设计方案和逻辑详细设计方案,要等这些 方案评审通过,认为可行了,才能进行编码,一般来说这部分工作所占的时间要远大于编码 的时间。 总体方案主要是涉及模块划分,一级模块和二级模块的接口信号和时序(我们要 求把接口信号的时序波形描述出来)以及将来如何测试设计。在这一级方案中,要保证在今 后的设计中时序要收敛到一级模块(最后是在二级模块中)。什么意思呢?我们在做详细设 计的时候,对于一些信号的时序肯定会做一些调整的,但是这种时序的调整最多只能波及到 本一级模块,而不能影响到整个设计。记得以前在学校做设计的时候,由于不懂得设计时序, 经常因为有一处信号的时序不满足,结果不得不将其它模块信号的时序也改一下,搞得人很 郁闷。 在逻辑详细设计方案这一级的时候,我们已经将各级模块的接口时序都设计出来了, 各级模块内部是怎么实现的也基本上确定下来了。
2.通过减少组合逻辑的减少时延。 上面我们讲了可以通过加约束来提高工作频率,但是我们在做设计之初可万万不可将提高 工作频率的美好愿望寄托在加约束上,我们要通过合理的设计去避免出现大的组合逻辑,从 而提高电路的工作频率,这才能增强设计的可移植性,才可以使得我们的设计在移植到另一 同等速度级别的芯片时还能使用。
我们通过给综合器加适当的约束(不可贪心,一般以加 5%裕量较为合适,比如电路工 作在 100Mhz,则加约束加到 105Mhz 就可以了,贪心效果反而不好,且极大增加综合时间) 可以将相关的逻辑在布线时尽量布的靠近一点,从而减少走线的时延。(注:约束的实现不 完全是通过改进布局布线方式去提高工作频率,还有其它的改进措施)
我们知道,目前大部分 FPGA 都基于 4 输入 LUT 的,如果一个输出对应的判断条件大于 四输入的话就要由多个 LUT 级联才能完成,这样就引入一级组合逻辑时延,我们要减少组合 逻辑,无非就是要输入条件尽可能的少,,这样就可以级联的 LUT 更少,从而减少了组合逻 辑引起的时延。
我们平时听说的流水就是一种通过切割大的组合逻辑(在其中插入一级或多级 D 触发器, 从而使寄存器与寄存器之间的组合逻辑减少)来提高工作频率的方法。比如一个 32 位的计数 器,该计数器的进位链很长,必然会降低工作频率,我们可以将其分割成 4 位和 8 位的计数, 每当 4 位的计数器计到 15 后触发一次 8 位的计数器,这样就实现了计数器的切割,也提高了 工作频率。
b.信号命名要规范化。
1) 信号名一律小写,参数用大写。
2) 对于低电平有效的信号结尾要用_n 标记,如 rst_n。
3) 端口信号排列要统一,一个信号只占一行,最好按输入输出及从哪个模块来到哪个模
块去的关系排列,这样在后期仿真验证找错时后方便很多。如:
module a(
//input
clk,
rst_n, //globle signal
FPGA 的输入时钟是 25M 的,现在系统内部要通过 RS232 与 PC 通信,要以 rs232_1xclk 的速
率发送数据。(不明白以后研究)
不要这样做:
always (posedge rs232_1xclk or negedge rst_n)
begin
...
end
而要这样做:
always (posedge clk_25m or negedge rst_n)