verilog仿真技巧与bug集合

1.初学者不建议在设计文件中加入仿真语句;
2.初学者也不会在tb里使用类似always一样的设计。

对于1.因为把仿真通过的HDL修改为可以综合下板的HDL是很难的一件事,但是适当的使用预编译ifdef来控制何时使用仿真语句,这样可以在设计文件需要综合时忽略仿真语句。在设计文件中使用仿真语句虽有风险,但是可以提现一个人的HDL能力(设计文件里加上initial真的很爽,很方便)
对于2.,使用的always设计通常是为了模拟某种时序而进行的描述,一般初学者只是使用initial,task来产生激励。

以前我也以为assign只能描述wire类型。但实际上也可以描述reg类型(还可以放always块里),还有deassign。
always 除了可以产生仿真的时钟,也可以 always #1 a = b;还可以做很多仿真的模拟时序协议的东西。

而initial除了简单的激励,还有task,repeat(重复多少次),wait(电平触发),@(边沿触发)可以用。多使用display、monitor,time,stop,finish,和写入文件的fopen,fdisplay,fclose,fwrite,fscanf,能提高很多仿真效率。

赋值语句

含延时的赋值语句

想法

always@()
case(a)
	0: assign b=c;

在实例化的时候接口可以用逻辑计算

.en( ~a & (b | c) )
wire[64*64+8*8+8 : 0] full;

generate for...
    always  #rd_period clkr[rd_period] = ~clkr[rd_period];//控制读周期,不可综合
    for...//0-7
        for...//0-7
	    例化模块
	    .clk( clkr[rd_period] ),
	    .full  ( full[64*rd_period + 8*wr_i+rd_i]     )//使得有一个特定的full信号连到例化的模块接口上。

这里声明一下上述的特定信号,应该是64 = 8*7+7+1这样推算出来的。
而不是64= 8*8。曾经花了一个半小时来debug找出来。。

一些建议

时钟信号

  1. 10M~1000M的信号用PLL生成(MMCM)比较好,往下的就手动分频(因为pll生成的5M时钟实际上可能只有4.125M )。

  2. 对于1.中生成时钟也可以使用create_clock的tcl指令来创建分频时钟。
    在这里插入图片描述

  3. 一个变量要得到时钟信号(或者分频),一定要用wire,assign
    assign clkr[9:0] = { 10 {clk_4M} };
    assign clkw = clk_20M;
    如果用了电平触发/边沿触发,这个变量会有一个相位延迟(就是触发时钟的一个周期)。注意,即使是电平触发也有延迟,always@(*)里描述的组合逻辑不等效于assign描述的组合逻辑.

关于异步fifo

写入数据时wp+1,读出数据时rp+1

如果读写是7bit深度(而fifo只有6bit,扩展1bit作为指针)。这里rp,wp都是因为读/写使能然后+1的(有些指针是统一操作一个指针,写就+1,读就-1)
rp=0,wp=127是不存在的。wp此时最多=64=7’b100_0000,rp=0=7’b000_0000。表示写满。
rp=127,wp=0是存在的。但是empty=0。这个要看具体的厂家对fifo的时序控制了。在本例里,wp=0是写了两圈数据,在第三圈一个数据都没有写入。读时钟上升沿,rp=127之后跳变到0,此时读出第二圈最后一个数据,这时候数据被读完empty=1。因此这种情况下,rp=wp=0才表示empty。

所以这种情况只能考虑 读写指针相同 empty=1;读写指针最高位不同,其余相同,full=1;不必也不能考虑指针一个最大一个为0的情况。

一些自己的bug

关于操作符&

  1. c= a & b ,ab相同但是c未必为1。因为0 & 0 =0。数电忘得干干净净。
  2. wire [3:0] a = 4’b1101;
    wire b = 1’b1;
    wire c = a & b;
    猜猜结果是啥,c=1’b1(默认c=a[0]&b[0])。在多比特和单比特 位与 的时候,要特别小心,两个数不同也能得到“相同”这个结果。

关于if-else

if
	if
else

上面的代码会被认为是

if
 	if
	else

正确的应该是:

if	begin
	if
end
else

关于modelsim使用

使用do脚本可以提高很多效率。在使用generate for来例化模块时,抓信号是非常头疼的。但是我们可以先抓一次想看的信号,保存为do脚本,然后将这段脚本剪切到其他空文件里,ctrl+H将genvar的变量直接替换:
在这里插入图片描述

这样就超级快得到了下一组想要抓的变量,而不必手动去抓信号。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值