这样计算累加是否合理?always后面必须跟wire?
-----------2/5少量修改代码全部使用阻塞赋值。
-----------2/8重新整理代码 vivado下面4种仿真结果都正确,唯独实现后时序模拟和上板跑用ILV debug看结果大很多,i比n会大一些,result更大,哪位能帮忙解释一下为什么会不准,怎么引入的误差,能否修正?写了一个用时钟边沿触发的逻辑可以正常工作,两者相比一个快但是不准,一个准但是很慢。在实现后模拟单步跟踪发现都是lut的一些操作,看不懂。
------------原文:
初学verilog, 计算1+2+....+N,两个问题:
1. 不用时钟,从vivado 2016.4模拟器看结果几乎是瞬间出现,这样是否合理?实际运行速度可能会怎样?实际设计中会怎样考虑这种计算?
- module SumNum(
- input clk,
- input [63:0] n,
- input n_next,
- output reg [63:0] result,
- output reg sum_done
- );
- reg[63:0] i = 1;
- wire [63:0] _i;
- assign _i = ~i;
-
- always @(_i, n_next)
- begin
- if (n_next == 0) begin
- i = 1;
- result = 0;
- sum_done = 0;
- end else begin
- if (i <= n) begin
- result = result + i;
- i = i + 1;
- end else
- sum_done = 1;
- end
- end
- endmodule
2. i是reg变量,_i是对应的wire变量,如果计算部分用always @(i) 总是不计算,只能用@(_i), 难道always只对wire敏感?还是说不能对自己修改的变量敏感?
一般来说是不合理的,通常一个周期累加一次。
从verilog语法上来说,没什么毛病。
从实际应用来说,这个代码没有意义,因为不具备可综合性。如果你学习verilog是做FPGA设计,建议可以先学习可综合风格的verilog,可以少走不少弯路。比如你这个问题,就没有人会去这么写。可综合风格的verilog仅仅只是verilog的一个小子集,但是对于做FPGA设计来说恰恰是用这个子集。到最后你会发现语言只是个工具而已,最重要的最难的其实是FPGA系统设计,不建议把大量时间花在不需要的语法的深究上。
回到你说的always@(*)的问题,按我的理解verilog语法里不存在对wire还是reg敏感,我觉得很有可能不同的编译器(模拟器/仿真器)对特定语句的解释都可能会不一样,所以还是要先学习可综合风格的verilog,保证代码在不同的工具下的执行一致。
楼上说的是,感觉你代码很别扭,很不舒服的感觉。就拿你的两个always来说,一个用阻塞赋值,一个用非阻塞赋值,你这个应该是没法综合的,i 明显的多个驱动源
这是通常做法?如果这样不用时钟能计算出来不是更好?
一个小建议, 刚入门时,除了自己多动手写代码外,还要多看看别人写的可综合代码。
非常感谢,初次接触这个语言,还在学习中。
组合逻辑,阻塞赋值,这只能仿真练习练习,不能综合去实用
哦?我专门按照dogbear2245的建议看了可综合语法,没说组合逻辑不能综合啊,再去研究一下。
哪里有官方文档给个明确限制列表?
很显然阻塞赋值可以被综合,一个很明显的例子就是使用always描述组合逻辑。
给你推荐一本书,对学习FPGA设计很有好处。当然,得有一定的基础。 《高级FPGA设计-结构、实现和优化》 机械工业出版社。
非常感谢,一定买来拜读!
另外请教verilog有没有一些开源IP网站,可以看看成熟的verilog怎么写?
再次感谢!
