FPGA加法截位处理方法介绍

描述

本模块实现输入与输出位宽相同数据加法,并对结果进行四舍五入截位,对标matlab round函数。
 

`timescale 1ns/1ns


module data_in_width_out_width_add_round #
(
    parameter DATA_WIDTH   = 16                             
)
(
    // 系统接口
    input                               i_clk_sys       ,
    input                               i_rst           ,
        
    // 数据输入
    input  signed   [DATA_WIDTH-1:0]    i_din_a         ,
    input                               i_din_a_vld     ,
    input  signed   [DATA_WIDTH-1:0]    i_din_b         ,
    input                               i_din_b_vld     ,
    
    // 数据输出
    output signed   [DATA_WIDTH-1:0]    o_dout          ,
    output                              o_dout_vld  
);


/****************************************************************************/
/*  parameter
/****************************************************************************/


/****************************************************************************/
/*  signal
/****************************************************************************/
logic signed    [DATA_WIDTH-1+1:0]  din_add_result          ;
logic                               din_add_result_vld      ;
logic signed    [DATA_WIDTH-1+2:0]  din_add_result_round    ;
logic signed    [DATA_WIDTH-1:0]    din_add_result_truncate ;        
logic                               din_add_result_vld_1dly ;
logic                               din_add_result_vld_2dly ;        
   
/****************************************************************************/
/*  process
/****************************************************************************/
always @(posedge i_clk_sys or posedge i_rst)                    // 数据加法
begin 
    if (i_rst)
    begin 
        din_add_result <= {{DATA_WIDTH+1}{1'b0}};
    end
    else 
    begin 
        din_add_result <= i_din_a + i_din_b;
    end
end


always @(posedge i_clk_sys)                
begin 
    din_add_result_vld <= i_din_a_vld && i_din_b_vld;
end


always @(posedge i_clk_sys)                                     // 数据四舍五入,根据要舍弃的位宽加不同的值
begin 
    if (din_add_result[DATA_WIDTH] == 1'b0)                     // 每次加法先扩充一个符号位,再对小数点位置进行 加减 0.5
    begin 
        din_add_result_round <= {din_add_result[DATA_WIDTH],din_add_result + 1'b1}; 
    end 
    else                                                        // 4'b1000}; +4bit 1是为了modelsim仿真,modelsim仿真规定小数至少3位
    begin 
        din_add_result_round <= {din_add_result[DATA_WIDTH],din_add_result - 1'b1};  
    end
end


always @(posedge i_clk_sys or posedge i_rst)                    // 数据截位
begin 
    if (i_rst)
    begin 
        din_add_result_truncate <= {DATA_WIDTH{1'b0}};
    end
    else if (din_add_result_round[DATA_WIDTH+1] == din_add_result_round[DATA_WIDTH])
    begin                                                       // 如果数据没有溢出,舍弃最后一位,赋值; 先补充符号位,再取表示起始bit为1,包含bit1并往上升DATA_WIDTH-1位
        din_add_result_truncate <= {din_add_result_round[DATA_WIDTH+1],din_add_result_round[1+ :(DATA_WIDTH-1)]};
    end
    else if (din_add_result_round[DATA_WIDTH+1] == 1'b0 && din_add_result_round[DATA_WIDTH] == 1'b1)
    begin                                                       // 如果正数溢出了,就给一个设置的位宽bit正数最大值,'h7fff 
        din_add_result_truncate <= {1'b0,{(DATA_WIDTH-1){1'b1}}};
    end
    else if (din_add_result_round[DATA_WIDTH+1] == 1'b1 && din_add_result_round[DATA_WIDTH] == 1'b0)
    begin                                                       // 如果负数溢出了,就给一个设置的位宽bit负数最大值,'h8000
        din_add_result_truncate <= {1'b1,{(DATA_WIDTH-1){1'b0}}};
    end    
end


always @(posedge i_clk_sys)                                     // 数据有效流水打拍
begin 
    din_add_result_vld_1dly <= din_add_result_vld;
    din_add_result_vld_2dly <= din_add_result_vld_1dly;


    o_dout                  <= din_add_result_truncate;
    o_dout_vld              <= din_add_result_vld_2dly;
end


endmodule

 

 代码中如果直接截位,数据的输出将会产生直流,所以需要对数据的符号位进行判断,并进行处理。简单的思路如下:

1.数据先进行加法。

2.对加法后的结果,进行判断,正数+0.5,负数-0.5,此操作用于去除直流。

3.再对去除直流后的结果,进行需要的截位取值,例如16bit+16bit=17bit,而最终的输出结果,如果要16bit,那就去掉末位,也可以只要15bit,去掉末2bit,只要bit15-bit2。

上述代码是简单的例子处理,输入进来的两种数据同位宽,输出也用同位宽输出。后续可以改进。



审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分