【问题标题】:what is the best way to implement right shift with signed number through verilog?通过verilog实现带符号数字右移的最佳方法是什么?
【发布时间】:2018-08-16 04:02:54
【问题描述】:

我正在尝试实现一段这样的 C 代码:

if (test_num>0)
    result = (test_num + offset) >> coeff;
else
    result = -((offset - test_num) >> coeff);

为了实现这一点,我做了这样的设计:

assign abs_result = test_num > signed(0) ? result : -result;

always @(*)
    case (coeff)
      4'd0: abs_result_tmp = abs_result;
      4'd1: abs_result_tmp = {1'b0, abs_result[7:1]};
      4'd2: abs_result_tmp = {2'b0, abs_result[7:2]};
      .....
      default: ...
    endcase

assign final_result = test_num > signed(0) ? abs_result_tmp : -abs_result_tmp;

因为我需要尽快完成这个功能,所以我不能使用寄存器来完成这个功能。只允许组合逻辑。我对这个 C 代码的 verilog 实现是最快的吗?还是有其他更好的解决方案来改善时间?谢谢

【问题讨论】:

    标签: verilog hardware fpga


    【解决方案1】:

    经典的verilog 不支持带符号的数字,也不会为您进行带符号的比较。虽然负数自然由 2-compliment cod 表示,并且将高位设置为“1”。假设您的 tes_num 是 32 位的,那么您总是可以测试 test_num[31] 的否定性。其余的应该像在“c”中一样工作,前提是你的结果大小和偏移量是相同的:

    input  [31:0] test_num;
    reg [31:0] result, offset;    
    always @*
      if (test_num[31] == 0) //positive numbers
        result = (test_num + offset) >> coeff;
      else
        result = -((offset - test_num) >> coeff);
    

    【讨论】:

    • 嗨,Serge,问题是如果 test_num 是“-1”,那么这段代码就不起作用。这就是我首先将 test_num 从signed 更改为“abs”并再次更改为signed 的原因。事实上,在现代模拟器中,例如irun,它支持签名模拟
    【解决方案2】:

    最简单的是将类型定义为有符号并使用>>>。

    另一种方法是重复 MS 位:(可能有错别字!)

    case (coef)
    4'd0 : result = test_num[7:0];
    4'd1 : result = {test_num[7],test_num[7:1]};
    4'd2 : result = {{2{test_num[7]}},test_num[7:2]};
    4'd3 : result = {{3{test_num[7]}},test_num[7:3]};
    ..
    endcase
    
    // This would be nice but I don't think it is allowed: {{coef{test_num[7]}},test_num[7:coef]};
    

    您希望 -1>>1 变为零。您实际上在做的不是符号移位,而是移位然后四舍五入。在 C 中 -1 >> 1 也将是 -1。 (因此,您的标题有些误导。:-) 这很好,因为有很多方法可以四舍五入。但请注意,如果您的 C 代码和 Verilog 代码使用不同的方案,将会出现差异。 (查找银行家四舍五入)。

    【讨论】:

    • 嗨 oldfart,我不认为重复 MS 位是正确的。你看,“-1”会被表示为0xff,当你右移一位时,“-1”应该是0。但是如果你重复MS位,这个“-1”将永远是“-1”
    • 嗨,oldfart,很抱歉我误解了您的回复。是的,如果您将类型定义为已签名并使用 >>>,那么您是对的,正如这篇文章所解释的那样:electronics.stackexchange.com/questions/132773/…。谢谢。
    • 嗨,oldfart,我只是尝试运行类型定义为已签名并使用“>>>”的模拟。大多数模拟似乎还可以,但由于 test_num= -1 失败了。右移 1 位时,仿真输出 -1。这似乎不对。所以我认为我的原始代码是正确的。我不知道在后端设计(我的意思是综合和布局)中实现时是否还有其他“合理”的代码可以更“快速”。谢谢
    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多