一段来自《Verilog HDL 高级数字设计》的错误Verilog代码

        笔者之前在阅读《Verilog HDL 高级数字设计》时的基4布斯乘法器一文时,就遇到了一段有问题的代码,而这个问题可以用Verilog基础:表达式位宽的确定(位宽拓展)文中的分析完美解决。

always @ (negedge clock) 
    if (Start) begin  
      expected_value = 0;  
      case({word1[word_size-1], word2[word_size-1]})
        0: begin expected_value = word1 * word2; expected_mag = expected_value; end
        1: begin expected_value = word1*  {`All_Ones,word2[word_size-1:0]}; 
            expected_mag = 1 + ~(expected_value); end
        2: begin expected_value = {`All_Ones, word1[word_size-1:0]} *word2;
            expected_mag = 1 + ~(expected_value); end 
        3: begin expected_value = ({`All_Zeros, 1 + ~word2[word_size-1:0]}) * ({`All_Zeros, 1 + ~word1[word_size-1:0]});
            expected_mag = expected_value; end
      endcase

        上面的代码片作用是根据word1和word2的不同算出乘积结果的数值大小和结果的数值绝对值大小。即当两个数都是负数时,即case 3,对两个数都整体取反加一变成正数(对于一个补码,获取其相反数补码的操作是对整体取反加一,包括符号位),然后相乘获得结果。但是里面存在问题,就是word的片选在取反之前会先补零拓展至32位,因为不带位宽的1是32位的,根据位宽拓展原则+和~这两个操作符都是上下文决定操作符,因此会先将word2[word_size-1:0]补零拓展(任何信号的片选都是无符号数)至32位,此时再取反就会变成一个很大的正数,因此会出错。

        对于比如8位有符号数-128和-127,按照上面转换后理想情况是128*127,但是因为错误的位宽拓展,结果变成了4294967168*4294967167。

        解决这个问题的方法很简单,将1改成1'b1即可阻止不必要的位宽拓展,或者用{}拼接操作符包围~word2[word_size-1:0],因为所有在{}符号内的操作数都会变成自决定操作数,位宽由自己决定而不加入上下文环境中,如下所示的为正确的代码。

always @ (negedge clock) 
    if (Start) begin  
      expected_value = 0;  
      case({word1[word_size-1], word2[word_size-1]})
        0: begin expected_value = word1 * word2; expected_mag = expected_value; end
        1: begin expected_value = word1*  {`All_Ones,word2[word_size-1:0]}; 
            expected_mag = 1'b1 + {~(expected_value)}; end
        2: begin expected_value = {`All_Ones, word1[word_size-1:0]} *word2;
            expected_mag = 1'b1 + {~(expected_value)}; end 
        3: begin expected_value = ({`All_Zeros, 1'b1 + {~word2[word_size-1:0]}}) * ({`All_Zeros, 1'b1 + {~word1[word_size-1:0]}});
            expected_mag = expected_value; end
      endcase

        上面的代码中,两种改正措施都实现了,实际上只需要其中一种即可。更多关于Verilog表达式位宽拓展和符号拓展相关的问题,可以查看下面的文章。

Verilog基础:表达式位宽的确定(位宽拓展)icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/article/details/128772558?spm=1001.2014.3001.5502Verilog基础:表达式符号的确定icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/article/details/128840843?spm=1001.2014.3001.5502

你可能感兴趣的:(数字IC,硬件工程,Verilog,fpga开发,Verilog高级数字设计)