本模块实现输入与输出位宽相同数据加法,并对结果进行四舍五入截位,对标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。
上述代码是简单的例子处理,输入进来的两种数据同位宽,输出也用同位宽输出。后续可以改进。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !