Verilog 语言和 VHDL 语言是两种不同的硬件描述语言,但并非所有人都同时精通两种语言,所以在某些时候,需要把 Verilog 代码转换为 VHDL 代码。本文以通用的 XHDL 工具为例对 Verilog 转换到 VHDL 过程中存在的问题进行了总结,欢迎批评指正。
当我们刚开始学习 FPGA 时,一定会遇到一个问题:
学习 Verilog 还是 VHDL?
等我们学习 FPGA 到一定程度参加面试时,面试者也会问你一个问题:
你以前用 Verilog 还是 VHDL 开发?
你已经习惯某种语言,也发现语言不是学习 FPGA 时需要考虑的问题,它仅仅是硬件描述语言工具而已。可是,当你发现一份和你使用语言不同的代码作为参考时,你又开始想:
我以后的工作是不是要二种语言都会,这样工作才会得心应手?
事实上,两种语言之间是可以相互转换的。
对于我们做 FPGA 开发人员来说,如何快速在 Verilog 和 VHDL 之间互转,加快开发产品的进度,而不是因为只懂某一种语言而局限了自己的开发。
Vivado 可以看两种语言的差异
Verilog 与 VHDL 语法是互通且相互对应的,如何查看二者对同一硬件结构的描述,可以借助 EDA 工具,如 Vivado,打开 Vivado 后它里面的语言模板后,也可以对比查看 Verilog 和 VHDL 之间的差异。
XHDL 软件
转换所用软件如下图所示:
上图是把转换成 VHDL 格式的代码,再转换回 verilog 后与原代码对比的图,可以看出,一些注释之类的信息都没有了,原来的代码规范和风格也发生了变化。
在转换的过程,该软件对代码中的汉语注释不支持,如果出现汉字就无法转换。
笔者之前就曾试着写过 Verilog 转 VHDL 代码的工具,见:Verilog HDL 代码转 VHDL 代码,无奈因为不是软件开发出身,写出来的东西通用性和完善性很差。写到此处,再次想起汉天下董事长杨清华所说的话,互联网讲究的是差异化的商业模式,很牛的产品定义,早期不看销售额而看流量,越快越好。这对 IC 是很可怕的事情,让整个产业变得很浮躁。**互联网的模式,在某种程度上是毒瘤。发展集成电路芯片,需要把互联网的模式认知去除。**芯片行业需要长期积累、持续关注,需要八年、十年的积累,这个耐心和耐性很重要。
试想一下,如果这么一个简单的小软件是互联网领域经常用到的,估计早已经遍地都是了吧,并且也都很好用呢!
以下仅对 Verilog 转 VHDL 过程中出现的问题进行说明。
Xhdl 软件转换后状态机的问题
含有状态机的 Verilog 代码被 xhdl 软件转换后会出现两种情况:
1、当 verilog 代码中 parameter 常量写在紧挨着端口位置时,xhdl 软件会将其转换为 vhdl 中的 generic 内的可传递的参数,如图:
2、当 parameter 在其它地方出现时,xhdl 会将其转换为 constant 常量,如图:
无论哪种方式,将其中有错误的地方改正后,都不会出现状态机运行出错,也就是不用将这种状态机书写方式更改为 vhdl 语法中专门的状态机书写方式。
function 转换位置出现问题
在用 xhdl 软件完成转换后会出现 function 写在了 process 块内的情况,出现此问题应将 function 改在 architecture 下面(与定义信号在相同的位置)。
信号只能赋值给与它位宽类型相同的信号
如下图中的两个信号:
b <= a;
在 verilog 中此种赋值方式意思是将 a 的前 3 位赋值给 b,但是在 vhdl 中此种赋值方式会报出位宽不匹配的错误,应将其更改为:
b <= a(2 downto 0);
同时需要注意 a、b 的数据类型必须相同,如图中必须都为 std_logic_vector 类型。
没有逻辑与,需用其它办法解决
在 vhdl 中没有逻辑与(verilog 中的&&),只有按位与(verilog 中的&,vhdl 中的 and),所以 verilog 中的逻辑与,在 vhdl 中有时需要用等价的方式替换,比如:
需要替换为:
注意数据类型转换符号使用的是否正确
在 vhdl 中有多种数据类型,它们之间可以通过数据类型转换符号相互转换。在 xhdl 软件中,数据类型转换一般都会出现错误,具体的原因是转换符号使用错误,而在 vhdl 的语法书上介绍的并不全面。下面介绍几中常用的数据类型转换符号:
1、IEEE.std_logic_1164.all 库中包含的:
(1)bit_vector to std_logic_vector :
<slv_sig> = to_stdlogicvector(bv_sig);
(2)std_logic_vector to bit_vector :
<bv_sig> = to_bitvector(<slv_sig>);
2、IEEE.std_logic_arith.all 库中包含的:
integer to std_logic_vector :
<slv_sig> = CONV_STD_LOGIC_VECTOR(<int_sig>,<integer_size>);
3、IEEE.std_logic_signed.all 库中包含的:
std_logic_vector to integer :
<int_sig> = CONV_INTEGER(<slv_sig>);
注意:选用某种数据类型转换符号的时候一定要确认是否包含了相应的库。
其它转换符号可以在如下图的 ise 软件相应的目录下查找
if 后的判断语句在某些情况会出现语法没错误逻辑出现错误
此种情况比较少见,但是一般很难发现,只有通过大量仿真找到错误。具体情况如下图:
原 verilog 代码:
if((MDR_port_i & outport) == 32'b0)
Xhdl 软件转换后语法无错误逻辑出现错误:
IF((MDR_port_i /= "0000000000000000000000000000000") AND outport /= "0000000000000000000000000000000" = false)
修改后:
IF((MDR_port_i AND outport) = "0000000000000000000000000000000" )
个人总结:在原 verilog 代码中,当 if 后的判断句出现按位与(&)时,Xhdl 软件转换成 vhdl 后很大可能会出现语法正确逻辑错误。
并置运算时遇到的问题
由于在 verilog 语法中,位宽不同的两个信号也可以相互赋值,但是在 vhdl 中对此有严格要求位宽相同,而 xhdl 软件在转换的时候不会检测这些,所以经常会出现位宽不匹配的情况,尤其是在并置运算时,所以要严格检查并置后的位宽与所赋值信号是否相同。
在 verilog 中某一信号可以赋值给几个并置的信号,但是在 vhdl 中不允许这么做,除非左侧并置的都为 std_logic 类型信号,右侧为 std_logic_vector 类型信号,注意此时在 vhdl 中并不是用“&”这个并置运算符,而是“,”。(bit 以及 bit_vector 是否有相似功能暂时未知)具体情况如图:
错误,因为 b 是 std_logic_vector 类型
正确情况如下图:
Bool 类型的运用以及会出现的问题
在 verilog 中几个信号经过关系运算后返回的值是 1 或者 0,但是在 vhdl 中返回的确是 bool 类型的值,也就是说返回的是 true 或者 false。
1、vhdl 中在 if 后的判断条件最后必须为布尔类型,如图:
2、verilog 和 vhdl 中信号经过关系运算后返回值的区别,如图:
When-else 语句不能用在 process 块内
软件转换后的 when-else 语句常常被放在 process 块内,导致出现问题。因为 when-else 语句是并行信号赋值语句,它本身就相当于一个进程 process,因此不能放在进程体中。进程是不能够嵌套的。
位移操作左侧为 bit 类型,右侧为 integer 类型
Verilog 中的位移运算经 xhdl 软件转换后必出现错误,错误的原因是转换成 vhdl 代码后位移符号两侧数据类型出错,如图
错误情况:
修改后的正确格式:
位移符号左侧应该是 bit 类型,所以将 std_logic_vector 类型的信号转换为 bit 类型,数字“63”默认为 integer 类型,位移后的结果仍然为 bit 类型,所以需要将其装换为 std_logic_vector 类型,并赋值给相同类型的信号。
真双口 RAM 的 IP 核的使能信号
注意真双口 RAM 的 IP 核的使能信号的数据类型,在顶层例化时要注意要只取使能信号第 0 位的与信号连接的方式。
由于真双口 RAM 在例化后“wea”“web”为 std_logic_vector(0 downto 0),所以要取这两个端口的 0 位与信号连接。
while 循环
在 vhdl 中不要使用 while 循环,会出现问题,将 while 循环换为 for 循环
top 层输入输出端口不接信号的情况
1、在 top 层,例化的某个模块输出端口不连信号时,只需要在例化此模块处将此端口删除或注释掉即可,如图:
2、当在 top 层例化的某一模块的输入端口无信号连接时,必须将此端口处连接“U(未初始化)”状态(理论上讲将“U”换为“Z”也可以,但实际上会报出语法错误,在 vhdl 语法书上说是连接“open”状态,实际测试也会报错),如图:
case 语句的注意事项
在 vhdl 的 case 语句的语法中,只有分支将所有条件都覆盖后才可以不使用“when others =>”(相当于 verilog 的 default),但是实际中几乎不可能包括所有情况(因为必须连高阻,不定态等状态都包含进去),所以需要在 case 语句分支条件增加“when others =>”。对于原 verilog 代码中 default 后没有任何表达式的情况,在 vhdl 中对应的地方写上“null”,如图:
组合逻辑转换时遇到的问题
当含有“always(*)”这类组合逻辑的 verilog 代码经 xhdl 软件转换后以下两种情况需要注意:
1、当是三段式状态机中的“always(*)”被转换时,注意去除其中的状态常量。
2、由于 vhdl 规定 case 后的判断条件必须是单一信号,所以当原 verilog 代码中,case 后面的判断条件不是单一信号,而是几个信号的组合时,xhdl 软件会将这几个信号的组合用组合逻辑赋给一个新的信号,后将新的信号放在 case 的判断逻辑处,此时需要注意查看组合逻辑块的触发信号是否包含此新生成的信号,具体如图:
仿真时注意时钟的问题(上板不会出现此问题)
在使用 modelsim 对 vhdl 代码进行仿真时,会出现如图的情况:
具体的操作就是对 c_o 信号打拍,可以发现第一拍没有打上(实际是打上了),该测试程序的原理图如图:
C 将时钟 clk_c_to_b 和一个信号 c_o 传递给 b,c_o 使用时钟 clk 生成的,在 b 内用 c 给的时钟来给 c_o 打拍。最后发现仿真之所以会出现上面的情况,主要是因为在模块 c 内对时钟 clk 进行了一次处理后赋给 b(如在 c 内部进行了 clk_c_to_b <= clk),导致出现了如下的波形情况:
如果你在使用 VHDL 与 Verilog 转换过程中遇到了上面没有提到的问题,欢迎留言讨论。或者你有更好的办法完成两种语言之间的转换,也请不吝赐教!
全文完。
END
来源:OpenFPGA
相关文章推荐
更多 FPGA 干货请关注 FPGA 的逻辑技术专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。