在Verilog上实现收件人的方法

时间:2016-03-01 23:39:33

标签: verilog xilinx hdl

我想在Verilog上实现一个后续块,后来将在FPGA上合成。输入应该是带符号的32位字长,其长度为16位。输出应该具有相同的格式。

实施例

  

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

我使用内置的IP内核分配器解决了这个问题。我想知道是否有一种优雅/替代的方法来解决这个问题,例如通过比特移位或2次补充来解决这个问题。

我已经使用IP内核来实现反向,正如它在手册中所说的那样但由于某些原因我并不真正理解结果是错误的,它需要向左移动1.例如; 1的加法给出0.5。 Recipical of 2给出1。

以下是手册和我的测试平台代码

中的一节

试验台

module reciprical_tb;

    // Inputs
    reg clk;
    reg [1:0] dividend;
    reg [31:0] divisor;

    // Outputs
    wire rfd;
    wire [1:0] quotient;
    wire [31:0] fractional;

    // Instantiate the Unit Under Test (UUT)
    reciprical uut (
        .rfd(rfd), 
        .clk(clk), 
        .dividend(dividend), 
        .quotient(quotient), 
        .divisor(divisor), 
        .fractional(fractional)
    );

    // clock
    always begin
        #5 clk = ~clk;
    end

    initial begin
        // Initialize Inputs
        clk = 0;
        dividend = 2'b1; // 1
        divisor = 2**16;; // = 1  when fraction length is 16bit

        // Wait 100 ns for global reset to finish
        #100;

        // Add stimulus here :: Inverse of 2 should give 0.5
        //$display("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.
        #100;
    end

endmodule

手册部分(第4页):

  

...   分隔符可用于实现X的倒数;这是1 / X功能。要做到这一点,   被除数位宽度设置为2并选择小数模式。然后将股息输入与01相关联   无符号或带符号的操作,X值通过除数输入提供。

使用Ip Core

GUI generator

2 个答案:

答案 0 :(得分:0)

IP核通常效率很高,但它们将使用结构倍增器和合理数量的逻辑。根据您所需的精度,也可以使用存储在Block RAM中的查找表来完成。使用原始输入作为地址的RAM对于设备而言将非常大。但是,您可以存储倒数曲线并预先缩放输入并在输出处应用移位。您可以通过在曲线上的两个点之间进行线性插值来进一步减少柱塞的使用。

这取决于您拥有的资源以及您需要的准确度。

答案 1 :(得分:0)

尝试调试部分问题:

你可以尝试一下:

    // 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后实际发射并输出更新后的值。