FPGA计算中定标与位扩展的实现

    我不知道名字取对没有,在FPGA计算中有时往往需要在不溢出的情况下将数扩大,从而获得更好的计算精度。

    比如。在一个8位宽的系统中,将x=0000_0010,算术左移m=5位之后得到xt=0100_0000,此时的xt参与运算之后能得到更好计算精度,并且通过m我们可以把相应的结果移位回来。

    典型的应用例子就是,使用cordic计算复数x+jy的相角与模值,那么此时我们可以在保证不溢出的情况下按比例的扩大(x,y),再进行cordic计算,此时我们就可以得到,将计算结果的模值右移相应的m位即可,那么我们就可以计算得到精度较高的模值与相角值。

 下面就是移位的过程。以一个8位的数据为例 x=0000_0010为例

     1.高四位全为符号位,所以,x<<<3=0_0010_000 m=3.

     2.高三位全为符号位,所以,x<<<2=0_10_00000 m=m+2=5.

    3.高两位不全为符号位,所以 x<<<0=0_10_00000 m=m+0=5.

 对应到每一次的硬件结构为

代码为:

module data_expand
#(
    parameter              DSIZE = 8,
    parameter              MSIZE = 3
)
(
    input clk,
    input                      nd,
    output                     rdy,
    
    input   signed [DSIZE-1:0] din,
    output  signed [DSIZE-1:0] dout,
    output         [MSIZE-1:0] mout
     
);

wire [DSIZE-1:0] dtemp [1:0];
wire [MSIZE-1:0] mtemp [1:0];
wire             rtemp [1:0];

data_expand_unit #(.DSIZE(DSIZE),.MSIZE(MSIZE),.K(3)) 
    i0 (.clk(clk), .nd(nd), .rdy(rtemp[0]), .din(din), .dout(dtemp[0]), .min('d0), .mout(mtemp[0]));
data_expand_unit #(.DSIZE(DSIZE),.MSIZE(MSIZE),.K(2)) 
    i1 (.clk(clk), .nd(rtemp[0]), .rdy(rtemp[1]), .din(dtemp[0]), .dout(dtemp[1]), .min(mtemp[0]), .mout(mtemp[1]));
data_expand_unit #(.DSIZE(DSIZE),.MSIZE(MSIZE),.K(1)) 
    i2 (.clk(clk), .nd(rtemp[1]), .rdy(rdy), .din(dtemp[1]), .dout(dout), .min(mtemp[1]), .mout(mout));


endmodule

module data_expand_unit
#(
    parameter              DSIZE = 8,
    parameter              MSIZE = 3,
    parameter [MSIZE-1:0]  K     = 3
)
(
    input                          clk,
    
    input                          nd,
    output  reg                    rdy,
    
    input       signed [DSIZE-1:0] din,
    output  reg signed [DSIZE-1:0] dout,
    
    input              [MSIZE-1:0] min,
    output  reg        [MSIZE-1:0] mout
     
);

always@( posedge clk )begin
    if( din[(DSIZE-1)-:(K+1)] == {(K+1){1'b0}} || din[(DSIZE-1)-:(K+1)] == {(K+1){1'b1}})begin
        dout <= din <<< K;
        mout <= min + K;
    end else begin
        dout <= din;
        mout <= min;
    end
    rdy <= nd;
end


endmodule

仿真结果如下:

 

posted on 2017-07-28 16:51  gNewplayer  阅读(1193)  评论(0)    收藏  举报