如果同学们的问题我们帖子里面没有的请第一时间联系我微信同步:18022857217吴老师,我们对新问题进行补充!
通过平时同学们反馈学习中经常用到的学习点,因此明德扬最近做了抖音系列短视频,都是一些FPGA学习技巧分享,大家感兴趣可以关注明德扬抖音号:87481069842。
内容不断更新!记得关注点赞学习不迷路!
【问题0】:关于阻塞赋值“=”和非阻塞赋值“<=”的讨论。
答:其实使用“=”还是“<=”的规则非常简单,就是:组合逻辑用“=”,时序逻辑使用“<=”。其他使用方法,都不符合硬件特性的。
记住上面规则,完全够用了,如果还想深究,可以看这个帖子:http://old.mdy-edu.com/zhijian/2021/0409/1255.html
【问题1】:关于 data[31 -cnt0*8 -:8]的含义。
答:简而言之,data[a -:b],是指最高位是a,并且往下数b个(包括a本身),等价于data[a : (a-b+1)]。
例1:data[15 -:8],就是最高位是15,往下数8个(包括15本身),即data[15 :8]。
例2:data[31-cnt0*8 -:8],是MDY很常用的选择语句,其中cnt0是计数器。当cnt0==0时,上式等于data[31 -:8] = data[31:24]。当cnt0==1时,上式等于data[23 -:8]=data[23 :16],依此类推。
更详细资料,请看MDY常用的数据选择语句 http://old.mdy-edu.com/wentijieda/20210409/1256.html
【问题1.1】请问:assign a_data_ff[15-8*cnt -:8] = data_a[7:0] ; 不知道为什么会产生 连续赋值 出错问题呢 ?
答:assign a_data_ff[15-8*cnt -:8] = data_a[7:0]。 这种使用方法,放在组合逻辑是不合适的,这里隐含了锁存器。
可以仔细阅读这句代码,当cnt==0时,其代码是:assign a_data_ff[15:8] = data_a[7:0],问题是,此时a_data_ff[7:0]怎么办?这代码没有说明,这通常会认为是保持不变。
组合逻辑里保持不变,就是锁存器的意思,这是不需要的。
【问题2】:关于数组的含义,即reg[7:0] data[3:0]的含义。
答:这个是verilog是数组的定义。按MDY的规则,其可以理解为:信号类型为reg[7:0]的类型,即8位reg型号线;后面的[3:0]是表示一共有4组。
然后data[0]是表示第0组reg[7:0] data的信号。
Verilog中数组的表示 http://old.mdy-edu.com/wentijieda/20210409/1257.html
【问题3】:VERILOG中正负数、小数的表示方法。
答:首先要明确,FPGA操作基本单位是“线”,这个线只有0或者1两种值,即可以认为FPGA操作基本单位是二进制值。其他如十进制数、十六进制表,均是设计师对二进制数的解释。
例如4'b1001,这是二进制值,在硬件表示有四根线,分别处于“高低低高”状态。
那么这四根线的“高低低高”是什么含义?设计师可以定义说,第一个高表示符号位,其他三个是数据值。设计师也可以说,前两根线表示整数,后两根线表示小数。
所以verilog的正负数、小数的表示方法,是没有约定的,是取决于工程师设计的。
关于更多的内容,可以参考下面贴子:FPGA中正负数和定点小数的表示方法 http://old.mdy-edu.com/zuixinyuanchuang/2019/1213/642.html
【问题4】:在设计文件中,如何确定信号是什么类型的?
答:在本模块中,用always设计的信号用reg型;在测试文件中,initial内部赋值的,用reg型;其他如例化信号、assign赋值的信号,都是用wire型。
注意,定义成reg型还是wire型,是没有物理意义,不要去强行解释为什么。
【技巧分享】在设计文件中,如何确定信号是reg型还是wire型?http://old.mdy-edu.com/wentijieda/20210408/1196.html
【问题5】:我设计了一个模块,并且模块命名为latch,为什么软件会提示错误。
答:latch是VERILOG关键词,不能用于自己设计的模块命名或者信号名。所以要注意关键词。【问题6:ALWAYS不写ESLE表示保持原来的值】:下面是一个ALWAYS语句,当rst_n==1、a==1时,led的值是多少?
答:当rst_n==1,a==1时,上图中第3、第6和第9行都不满足条件,因此第4、7、10行的赋值语句都不会执行。也就是说led值没有改变。所以,时钟上升沿之后,led还会保持原来的值。如果原来的led等于0,之后也是0;原来等于1,之后也是等于1.
【问题7】左移和右移,空出的位置是补0吗?
【问题8】为啥begin后面加这个冒号,以前没见到过。
答:begin后面加冒号,相当于这个begin end块起一个名字。起名字是做区分用,一般情况下,不对begin/end命名,所以这种写法很少见。
【问题9】在verilog中到底应不应该用for循环?
答:在硬件描述语言中for语句的使用较C语言等软件描述语言有较大的区别。在Verilog中除了在Testbench中使用for语句外,在RTL级编码中是却很少使用for循环语句。
另外,MDY不建议“硬件不熟练”的人使用for循环进行逻辑开发。因为FPGA设计,本身是硬件设计,即使用了for,也要清楚地知道会综合成什么样电路,有多少寄存器和加法器等,这是逻辑设计的最基本要求。
很多人为了求“脑力”的省事、不加理解就用for,会很容易写成不可综合的C语言代码,这本身就是不正确的。
还要明确一点QUARTUS、VIVADO甚至IC综合器,对for语法的解析流程。
首先,这些工具是先把带有for循环的verilog,转成不带for循环的verilog(注意此时还是verilog代码);然后再对转后的verilog进行综合,变成电路。
前面的for循环转换,其实就是对代码进行复制了。
【问题10】在Verilog中想要给一个信号赋值的位宽是可变的,应该怎么做?
答:可以使用下面这个赋值方法:{WID{1'b1}}举例:din <= {WID{1'b1}},当WID为8的时候,din <= 8'b1111_1111,通过修改WID的值,可使赋值的位宽发生变化。【问题11】data[b+7:b]<=rx[a+7:a]
老师我想用for循环动态给data的区间赋值,但是报错说b不是常量怎么办?答:verilog中不支持位宽选择时 上边界和下边界均为变量。另外:不要用软件的思维来做FPGA设计
【问题12】提示endmodule语法错误?这个能有什么错误呢?如下图:
答:像这种提示哪几种错误的,就打开代码,找到这一行,前前后后,检查代码有哪些与“平常”不一样的地方。如果 清楚,可以打开一个已经OK的代码,来代码下。
【问题13】请问以下变量后加个"-"意思是取这个变量的某几位吗?
答:上面的按减号带入结果就可以了,例如 data[7-1],就是data[6]。 data[7-1:0],就是data[6:0]。
【问题14】问能不能在适中的下降沿采集数据呢,比如写成always@(negedge clk)
假如上升沿发数据,下降沿来采集(或者下降沿发数据,上升沿采集),相当于时钟周期减半了,时序要求更高了。
【问题15】二进制000-二进制001=111 这个最高位怎么算的?
所不同的是:二进制是 0-0=0,0-1=1,1-0=1,1-1=0。
如果保存结果的位宽只保留最低位的话,那就是111。
更多更详细的资料,请看《FPGA至简设计原理与应用》:http://old.mdy-edu.com/wentijieda/20210414/1331.html?1618393457,请看第一篇,第三章5.3 算术运算符的内容。
【问题16】rst_n==1'b0 和!rst_n不同的问题。
LED灯设计为什么LED和计数器复位条件不一样?
答:这两个结果是一样的,都是当rst_n为1时复位。只是写法不同。
【问题17】请问各位老师同学 如何用modelsim获取一段代码的运行时间? 谢谢
【问题18】a[0:0]表示什么意思呢?
【问题19】data[0] <= data_b [0][2]表示什么意思?
答:将data_b看作一个矩阵,表示调用矩阵的第0行第2个数据。【问题20:一个always里有多少信号时的理解问题】如下图所示,第9行代码里的key_reg值,是等于第8行的key的值还是key_reg的值。是先执行第8行,再执行第9行代码吗?
答:当一个always里设计了多个信号时,如上图中设计了key_reg和delay_cnt的值,其实质可拆分成如下代码。
答:当一个always里设计了多个信号时,如上图中设计了key_reg和delay_cnt的值,其实质可拆分成如下代码。
而众所周知,verilog代码中每个always都是独立并且同时执行的。
因此上图中第23行的代码和第32行的判断是同时进行的。假设当前key_reg等于0。在时钟上升沿前key等于1。那么第23行执行后,key_reg值更新为1。同时第32行判断时key_reg值仍然为0,不是最新的值为1。
在此,MDY强烈建议,一个ALWAYS设计一个信号,有助于做逻辑设计,理清思路,避免很多理解上的问题。而且事实上,一个always设计多个信号更像写“软件”的代码,是用软件思维在设计FPGA,而在FPAG中是不规范的。
【问题21】 always 语句中,不论是赋值 还是 比较,都是针对 时钟上升沿到来前的 前面一点点时刻的 寄存器中的数据 来赋值 和 比较的。
答:是的。具体请看下面的波形图规则 :http://old.mdy-edu.com/plus/view.php?aid=1333
【问题22】问一下关于敏感信号的事情,任何信号都可以被当作敏感信号吗?也就是always模块里面:always @(posedge din_vld or negedge rst_n)begin这样写可以吗?
【问题23】复位信号必须要放到敏感信号列表吗?
【问题24】多个模块的输出信号,可以连到一起,共同驱动另一个模块吗?
共同均有一个模块C的输入信号c。那么存在这种情况,模块A要输出1,模块B要输出0给模块C,那么模块C收到的是0还是1呢?这种情况下,模块C就不清楚收到什么了。
所以本题答案:两个模块的输出信号不能连在一起。
【问题25】组合逻辑电路可以有反馈吗?
【问题26】写的代码太复杂/未遇到的语法,不理解/,代码不知道哪里错了/等问题
1. 将复杂代码,使用简单代码代替。
2. 或者,将代码分解,每添加一行看不行结果,以方便定位哪里有问题。
【问题27】什么时候使用组合逻辑,什么时候使用时序逻辑?
【问题28】VERILOG语法中,signed类型的作用。
1.在verilog中有时会用signed修饰符来修饰定义的数据,运算的时候也会用$signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?
其实不是的,因为有符号数和无符号数据的加法强结果和乘法器结构是一样的,signed的真正作用是决定如何对操作数扩位的问题。
【问题29】VERILOG中定义的类型,是怎么分辨是有符号数、无符号数、或者16进制数的。
答:要真正理解一点,FPGA的信号,其本质上是二进制数。例如4'b1010。至于这个二进制数,是有符号数,还是无符号数,都是取决于工程师的解释。例如4'b1010,可以理解为无符号数10,也可以理解为有符号数原码-2,也可以理解为有符号数补码-6。更多解释,请看《FPGA至简原理与应用》一书中关于verilog和补码由来这一部分:http://old.mdy-edu.com/zhijian/2021/0409/1239.html
【问题30】在FPGA计算中,对于a+b等,对a和b是根据无符号数,还是有符号数来计算的?
答:再次强调,真正理解:FPGA信号本质是二进制数。 无论a和b是什么类型的信号,最终都是换算成二进制来计算,自然的遵守二进制计算基本法则,
具体请看:http://old.mdy-edu.com/zhijian/2021/0409/1237.html
【问题31】请问generate的使用方法
答:可以参考如下文章: 【教程】generate语法_FPGA-明德扬/专业FPGA解决方案专家 (mdy-edu.com)
【问题32】请问信号定义时,输出类型的定义和信号类型的定义可以放到一起写吗?
【问题33】len <= {len[7:0],din},len信号的位宽为16bit,din的位宽为8bit,这段代码的意思是什么?
第二次进行赋值时,len[7:0]为8’h55,din为8‘hd5,拼接之后赋值给len。此时len=16’h55d5。
【问题34】红色箭头指的那些语句是什么意思?
答:这是宏定义的的一种用法。此时表示该.v文件使用的是从“ 'ifndef SIMPLE”到“ 'endif”以外代码,如果把“' define SIMPLE”注释掉的话,使用的就是从“ 'ifndef SIMPLE”到“ 'endif”以内的代码。
【问题35】好多个模块是只编译顶层模块就可以了吗?
答:无论是仿真还是综合,其综合都是从顶层模块开始的。通过调用顶层模块,然后根据顶层模块的例化代码,就能找到下一层模块,逐级找下去,就能找到所有使用到的模块了
【问题36】fpga乘法可以直接用*吗?
【问题37】问:例化的时候,如果对接口留空是什么结果
答:例化的时候,如果是模块的输入信号,留空的话表示输入0。如果是输出信号,留空的话,没有影响。
【问题38】这个4bit MCU_FSMC_data[0], 拼接有简单的写法吗?
答:data_4 <= {4{MCU_FSMC_data[0]}};
【问题39】这是明德杨语法课的一段代码,左边的写法为什么是错误的呀?
答:那是软件思维,软件思维就是先执行第1行,再执行第2行;右边是硬件思维,在描述b信号的功能。
【问题40】ALWAYS里的 if else是否有优化级?是按顺序判断的吗?
答:是否理解“else”的意思?中文含义是叫“否则”,否则是指一个条件的否则。也就是说前面条件不满足,然后再看此条件。
【问题41】代码中,“if(0)”是什么含义?如下图。
答:verilog里面,if是条件判断语句,如果括号里为真,则执行,则假则不执行。if(0),括号里条件是假,所以不执行。
因此上面代码中,条件写成if(0)就是表示永远不执行的意思。
有人好奇为什么这么写?这不是毫无意义吗?嗯,具体原因可以问作者,可能是前期代码要用到,后期发现不用了,又懒得改太多,就写成0吧。
【问题42】FULL和是A_WIDTH都是parameter,FULL[A_WIDTH]是什么表达方式呢?
答: []在VERILOG里用于表示第几比特,例如a[0]表示a的比特0位,a[1]表示a的比特1位。程序里(包括verilog或者c语言)不管定义成什么类型,其最本质的就是二进制数。
使用parameter定义了FULL和A_WIDTH,其也是二进制数,所以FULL[A_WIDTH],自然就是FULL的比特A_WIDTH位。
【问题43】always那个括号里面的*号代表什么意思? 答:加“*”是组合逻辑的写法。当敏感信号非常多时很容易就会把敏感信号遗漏,为避免这种情况可以用“*”来代替。这个“*”是指“程序语句”中所有的条件信号,即 a,b,d,sel (不包括c),也推荐这种写法。
【问题44】Verilog报错的原因及解决方案
【问题45】Error (10663): Verilog HDL Port Connection error at wave.v(31): output or inout port "dataouthc" must be connected to
a structural net expression模块例化时数据类型的错误。
【问题46】请问阻塞和非阻塞赋值之间有什么区别?
2.always_comb:专门用于建模组合逻辑; 3.always_latch:专门用于建模锁存器;
答:问题出现在把复位信号设置成上升触发,而后又判断是否为低电平。将其改成:
答:这个问题可以参考答疑帖:http://old.mdy-edu.com/wentijieda/20210410/1264.html
【问题53】怎么理解位宽就是[?:0]的? |
【问题54】问:上升沿检测,为什么不能直接使用posdedge来检测?
答:数字电路中,所有电路都是在时钟的节拍下进行工作。时钟是稳定并且有节奏的。对应的是代码ALWAYS中,
敏感列表里posedge中一般就连接clk,而不能连其他。如果连了其他,就不是稳定的数字系统
德扬除了培训学习还有项目承接业务,擅长的项目主要包括的方向有以下几个方面:
1. MIPI视频拼接
2. SLVS-EC转MIPI接口(IMX472 IMX492)
3. PCIE采集系统
4. 图像项目
5. 高速多通道ADDA系统
6. 基于FPGA板卡研发
7. 前端模拟采集、射频、电荷灵敏前置放大器
需要了解相关信息可以联系:吴老师18022857217(微信同号)