CrazyBingo

Verilog HDL非预测问题分析

0
阅读(3225)

Verilog HDL非预测问题分析

总是在不停的前进,总是在不停的徘徊,总是在不停的寻找,总是在不停的修复……只有不停的探索,才有可能突破极限,毕竟:Perfect has no limitation!

问题1:

去年遇到过一个蛋疼的问题,也许是因为基础不扎实,当让也不排除粗心的可能性,在移位的时候差点想崩溃……

mY <= Y<<9 + Y<<6 + Y<<4 + Y<<2;

如上以为代码所示:当时调试摄像头,将YUV色度空间转换到RGB,途中将乘除法巧妙转换位了移位算法,但是实际调试中百思不得其解。。。最后被人一板砖,原来是优先级的问题,废话不多说,直接改下下面就OK:

mY <= (Y<<9)+(Y<<6)+(Y<<4)+(Y<<2);

问题2:

(1)ACK <= ACK1 | ACK2 | ACK3;

(2)ACK <= (~ACK1 & ~ACK2 & ~ACK3);

(3)ACK <= ((ACK1 == 1'b0) && (ACK2 == 1'b0) && (ACK3 == 1'b0)) ? 1'b1 : 1'b0;

如上三种ACK的表达式,描述的电路为了达到ACK1,ACK2,ACK3同时为0的时候,输出1,然而(1)可行,(2)不可行,(3)竟然也不可行。。。

参照问题1,很好解释(2)不行,可是(3)为什么不行,死也无法给自己一个交代。。。。。。

问题3:

阻塞赋值和非阻塞赋值,很多人都茫茫然的。。。

看过有些人的代码,相当然的这样描述电路,说是综合之后都一样,无所谓:

always@(posedge clk or negedge)
begin if(!rst_n)
        dout = 0; else dout = dout + 1'b1;
end

当然实际RTL图看起来的确没啥问题。。。

然则,勿以恶小而为之,当"<="和"="出现在同一个模块中时,一山不容二虎,意想不到的问题发生了,请看下面一段代码:

reg    i2c_transfer_en; //send i2c data    before, make sure that sdat is steady always@(posedge clk or negedge rst_n) begin if(!rst_n)
        begin
        clk_cnt <= 0;
        i2c_transfer_en <= 0;
        end else if(delay_done)
        begin if(clk_cnt < (CLK_FREQ/I2C_FREQ) - 1'b1)
            clk_cnt <= clk_cnt + 1'd1; else clk_cnt <= 0;
        i2c_transfer_en = (clk_cnt == 16'd0) ? 1'b1 : 1'b0;
        end else begin
        clk_cnt <= 0;
        i2c_transfer_en <= 0;
    end
end

有问题吗?。。。好像没问题,那就没问题吧。。。。继续写下面一段,状态转移,行云流水滔滔不绝,唰~~~

    //Write I2C: {ID_Address, REG_Address, W_REG_Data} I2C_WR_START:
        begin if(i2c_transfer_en)    next_state = I2C_WR_IDADDR; else next_state = I2C_WR_START;
        end

准备完毕。习惯性用modelsim前仿,通不过modelsim的面试,死也不会用Quartus II综合。仿真图如下,一切尽在不言中……

wps_clip_image-21631

wps_clip_image-4793

wps_clip_image-32284

然则:

出现了一个状态1跳转到状态,以及状态2跳转到状态2,这未免太神奇了,无限倍的方法1-1或者2-2之间的状态,也没有出现异常的心情,干干净净的1或2,百思不得其解吗,想撞墙,崩溃了一个下午……

手贱打开Quartus II编译一下,惊奇的发现了傻瓜式的错误如下:

wps_clip_image-5227

Warning (10268): Verilog HDL information at i2c_timing_ctrl.v(75): always construct contains both blocking and non-blocking assignments

回归到代码中,我竟然:

        i2c_transfer_en = (clk_cnt == 16'd0) ? 1'b1 : 1'b0;

所谓一山不容二虎,而我却……这个看起没问题的问题,在状态上的后续操作造成了不可磨灭的bug。。。。

        i2c_transfer_en <= (clk_cnt == 16'd0) ? 1'b1 : 1'b0;

不知道是自己敲太快了还是怎么,反正就是手贱了。。。重新修改i2c_transfer_en电路,如上所示。。。再次modelsim编译,干得漂亮。。。。

wps_clip_image-10249

有些FPGA初学者,甚至从来不看Quartus II Waiming,认为警告不是错误,一撸而过。。。。而太多的时候,警告其实也是错误。。。比如:“警告处分”。。。。

Verilog HDL代码规范,风格,太重要,太重要。。。组合、时序、同步、异步。。。好的代码,可以避免时序违规,可以达到速度和面积的性价比,甚至可以省略时序约束。。。。

十年磨一剑,跌跌撞撞4年了,还是觉得自己是个菜鸟。。。。。