在Verilog上实现recipricals的方法

在Verilog上实现recipricals的方法,verilog,xilinx,hdl,Verilog,Xilinx,Hdl,我想在Verilog上实现一个交互块,稍后将在FPGA上合成。输入应为带符号的32位字长和16位小数长度。输出应具有相同的格式 范例 输入:x-->输出---->1/x 我已经解决了这个问题,使用内置的IP核心分配器。我想知道是否有一种优雅的/可选的方法来解决这个问题,例如通过位移位或2的补加一些异或研磨 我已经使用IP核心实现了手册中所述的反向,但由于某种原因,我并不真正理解结果是错误的,需要将其向左移动1。例如1的倒数等于0.5。2的倒数等于1 下面是手册和我的测试台代码的一部分 试验台

我想在Verilog上实现一个交互块,稍后将在FPGA上合成。输入应为带符号的32位字长和16位小数长度。输出应具有相同的格式

范例

输入:x-->输出---->1/x

我已经解决了这个问题,使用内置的IP核心分配器。我想知道是否有一种优雅的/可选的方法来解决这个问题,例如通过位移位或2的补加一些异或研磨


我已经使用IP核心实现了手册中所述的反向,但由于某种原因,我并不真正理解结果是错误的,需要将其向左移动1。例如1的倒数等于0.5。2的倒数等于1

下面是手册和我的测试台代码的一部分


试验台 手册部分(第4页):

。。。 除法器可用于实现X的倒数;这就是1/X函数。要做到这一点 红利位宽度设置为2,并选择分数模式。然后,股息输入与01相关联,用于 无符号或有符号运算以及X值都是通过除数输入提供的

使用的Ip核
IP核通常非常高效,但它们将使用结构乘法器和合理的逻辑量。根据您需要的精度,也可以使用块RAM中存储的查找表来完成。使用原始输入作为地址的RAM对于设备来说太大了。但是,您可以存储一条倒数曲线,预缩放输入并在输出处应用偏移。通过在曲线上的两点之间进行线性插值,可以进一步减少ram的使用


这取决于您拥有的资源和所需的准确性。

尝试调试问题的一部分:

你能试试吗

    // Wait 10 clock cycles
    repeat (10) begin
      @(posedge clk);
    end

    // Add stimulus here :: Inverse of 2 should give 0.5
    $display("dsiplay inv(%g) =>  %g || inv = %b",$itor(divisor)*2.0**-16, $itor(fractional)*2.0**-16, fractional); //gives zero
    $monitor("inv(%d) => q = %d || inv = %b", divisor>>>16,fractional>>>16, fractional);  //gives a wrong answer by a factor of 2
    // Using the monitor i get inv(1) = 0.5 instead of 1.
    // Wait 10 clock cycles
    repeat (10) begin
      @(posedge clk);
    end
    $display("dsiplay inv(%g) =>  %g || inv = %b",$itor(divisor)*2.0**-16, $itor(fractional)*2.0**-16, fractional);

    //End simulation
    $finish();

由于监视器只发出一次,它可能在200ns之后实际触发并输出更新的值。

我建议更换
#100带有
#100ns这将消除对模拟时间设置的依赖。时钟源中的
#5
也是如此。我得到一个错误,表示未声明。当我写
#100ns
啊,好的。从技术上讲,这是系统verilog语法,但据我所知,大多数verilog模拟器都允许它。@user3697625更新了问题,改为等待10个时钟周期,并使用$finish结束sim,因为可能是stdout没有正确刷新。
    // Wait 10 clock cycles
    repeat (10) begin
      @(posedge clk);
    end

    // Add stimulus here :: Inverse of 2 should give 0.5
    $display("dsiplay inv(%g) =>  %g || inv = %b",$itor(divisor)*2.0**-16, $itor(fractional)*2.0**-16, fractional); //gives zero
    $monitor("inv(%d) => q = %d || inv = %b", divisor>>>16,fractional>>>16, fractional);  //gives a wrong answer by a factor of 2
    // Using the monitor i get inv(1) = 0.5 instead of 1.
    // Wait 10 clock cycles
    repeat (10) begin
      @(posedge clk);
    end
    $display("dsiplay inv(%g) =>  %g || inv = %b",$itor(divisor)*2.0**-16, $itor(fractional)*2.0**-16, fractional);

    //End simulation
    $finish();