verilog float mult

复制代码
module pipe_float_mul
    (
        input wire           clk                        ,// 时钟信号
        input wire           en                         ,// 使能信号
        input wire           rst_n                      ,// 复位信号
        input wire           round_cfg                  ,// 决定舍入的方法,0采用chopping,1采用就近舍入 
        input wire  [31:0]   flout_a                    ,// 输入的被乘数
        input wire  [31:0]   flout_b                    ,// 输入的乘数
        output reg  [31:0]   flout_c                    ,// 输出运算结果
        output wire          valid_flout_c              ,
        output reg  [1:0]    overflow                    // 输出溢出标志    
    ); 


 reg            s1, s2;                     // 输入数符号
 reg [7:0]      exp1, exp2;                 // 输入阶码
 reg [23:0]     man1, man2;                 // 输入尾数,多一位,把默认的'1'加上
 reg            n;                          // 左归阶码
 reg [9:0]      temp1, temp2, temp3;        // 多两位,用于阶码的双符号表示,判断溢出
 reg [47:0]     mul_out_p;                  // 第二级逻辑运算尾数部分

 //-------'s'为符号,'e'为阶码,'m'为尾数------------//
 //第一级逻辑输出
 wire         one_s_out;
 wire [9:0]   one_e_out;
 reg  [47:0]  one_m_out;
 
 //第一级流水寄存
 reg        one_s_reg; 
 reg [9:0]  one_e_reg; 
 reg [47:0] one_m_reg;
 

 //第二级逻辑输出
 reg [1:0]  two_f_out; //溢出
 reg [7:0]  two_e_out; 
 reg [22:0] two_m_out; 

 //第二级流水寄存
 reg        two_s_reg;
 reg [1:0]  two_f_reg; //溢出
 reg [7:0]  two_e_reg;
 reg [22:0] two_m_reg;
 
 reg [4:0]  cnt_delay   ;

assign  valid_flout_c = ( cnt_delay == 5'd3 )?1'b1:1'b0 ;
/*---------------提取flout_a 的符号,阶码,尾数---------------------*/
always @(posedge clk or negedge rst_n) begin
   if (!rst_n) 
   begin      //复位,初始化
      s1        <= 1'b0;
      exp1      <= 8'b0;
      man1      <= {1'b1, 23'b0};
      cnt_delay <=  5'd0    ;
   end
   else 
   begin
       if( cnt_delay == 5'd5 )
       begin
           cnt_delay <= 5'd0   ;
       end
       else if( en == 1'b1 )
       begin
            cnt_delay <=    5'd1    ;
       end
       else if( cnt_delay >= 5'd1 )
       begin
            cnt_delay   <=  cnt_delay + 1'b1    ;
       end
       else if( cnt_delay == 5'd0 )
       begin
            cnt_delay   <=  5'd0    ;
       end
       else
       begin
            cnt_delay   <=  cnt_delay   ;
       end
    if (en == 1'b1 ) 
    begin
        s1   <= flout_a[31];
        exp1 <= flout_a[30:23];
        man1 <= {1'b1, flout_a[22:0]};
    end
   end
  
end
 
/*---------------提取flout_b 的符号,阶码,尾数---------------------*/
always @(posedge clk or negedge rst_n) begin
   if (!rst_n) begin      //复位,初始化
      s2   <= 1'b0;
      exp2 <= 8'b0;
      man2 <= {1'b1, 23'b0};
   end
   else if (en) begin
      s2   <= flout_b[31];
      exp2 <= flout_b[30:23];
      man2 <= {1'b1, flout_b[22:0]};
   end
end

/*--------------------第一级逻辑运算---------------------------------*/
//符号位
assign one_s_out = s1 ^ s2;   //输入符号异或
 
//尾数相乘
always@(*) begin
   if (man1 == 24'b10000000000_0000000000000)
	   one_m_out = 48'b0;
	else if (man2 == 24'b10000000000_0000000000000)
	   one_m_out = 48'b0;
	else
	   one_m_out = man1 * man2;  //48位
end

//阶码相加,阶码是移码,移码是符号位取反的补码
always@(*) begin
   //把阶码的移码形式变为补码形式,并且转成双符号位格式,00为正,11为负
   if (exp1[7] == 1)
      temp1 = {2'b00, 1'b0, exp1[6:0]};
   else 
	   temp1 = {2'b11, 1'b1, exp1[6:0]};
   if (exp2[7] == 1)
      temp2 = {2'b00, 1'b0, exp2[6:0]};
   else
	   temp2 = {2'b11, 1'b1, exp2[6:0]}; 
end

//阶码以双符号补码的形式相加计算
assign one_e_out[9:0] = temp1[9:0] + temp2[9:0];  

/*--------------------第一级流水寄存---------------------------------*/
always@(posedge clk or negedge rst_n) begin
   if (!rst_n) begin
       one_s_reg <= 1'b0;
	   one_e_reg <= 10'b0;
	   one_m_reg <= 48'b0;
   end
   else begin
       one_s_reg <= one_s_out;
	   one_e_reg <= one_e_out;
	   one_m_reg <= one_m_out;
   end
end

/*--------------------第二级逻辑运算---------------------------------*/
//尾数规范化及舍入处理,溢出判断
always@(*) begin
   if (one_m_reg == 48'b0) begin  // 处理特殊值
       two_m_out =  23'b0;
       n  =  1'b0;
   end  
	else begin
		if (one_m_reg[47] == 1) begin
		    n  = 1'b1;                    // 左归码为1
			 mul_out_p = one_m_reg >> 1;  // 右移一位
	   end
	   else begin
			 n   = 1'b0;                  // 左归码为0
			 mul_out_p = one_m_reg;       // 不需要右移
	   end
	   if (round_cfg == 1) begin          // 0采用chopping,1采用就近舍入 
		   if (mul_out_p[22] == 1)
			    two_m_out[22:0] = mul_out_p[45:23] + 1'b1;
			else
			    two_m_out[22:0] = mul_out_p[45:23];
	   end
		else  
         two_m_out[22:0] = mul_out_p[45:23];
   end
   // 双符号的定义,01为上溢,10为下溢,符号相同无溢出
   temp3 = one_e_reg[9:0] + n + 1'b1;  // 加上左归阶码,因为补码与移码的转换是-128,而IEEE是-127,故加上1
	if (temp3[9:8] == 2'b01)  
        two_f_out = 2'b01; //阶码上溢
   else if (temp3[9:8] == 2'b10)  
	    two_f_out = 2'b10; //阶码下溢
   else 
	    two_f_out = 2'b00; //无溢出
	//输出补码转回移码
   case(temp3[7])  
     1'b1 :  two_e_out = {1'b0,temp3[6:0]}; 
     1'b0 :  two_e_out = {1'b1,temp3[6:0]}; 
   endcase
end

/*-------------------第二级流水寄存------------------------------------*/
always@(posedge clk or negedge rst_n) begin
   if (!rst_n) begin
       two_s_reg <= 1'b0;
	   two_e_reg <= 8'b0;
	   two_m_reg <= 23'b0;
	   two_f_reg <= 2'b0;
   end
   else if ((two_m_out == 0) && (two_e_out == 0)) begin   //特殊值处理
	   two_s_reg <= 1'b0;
	   two_e_reg <= 8'b0;
	   two_m_reg <= 23'b0;
	   two_f_reg <= 2'b0;
	end
   else begin
       two_s_reg <= one_s_reg;
       two_f_reg <= two_f_out;
       two_e_reg <= two_e_out;
       two_m_reg <= two_m_out;
	end
end

//输出结果
always@(*) begin
	  flout_c  = ( valid_flout_c == 1'b1 )?{two_s_reg, two_e_reg[7:0], two_m_reg[22:0]}:32'd0;
	  overflow = two_f_reg;
end

endmodule

tb

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/19 15:16:46
// Design Name: 
// Module Name: tb_pipe_float_mul
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_pipe_float_mul();

    reg           clk                   ;// 时钟信号
    reg           en                    ;// 使能信号
    reg           rst_n                 ;// 复位信号
    reg           round_cfg             ;// 决定舍入的方法,0采用chopping,1采用就近舍入 
    reg  [31:0]   flout_a               ;// 输入的被乘数
    reg  [31:0]   flout_b               ;// 输入的乘数
    wire [31:0]   flout_c               ;// 输出运算结果
    wire [1:0]    overflow              ;// 输出溢出标志
    wire          valid_flout_c         ;
    
    initial
    begin
       clk          =   1'b0    ;
       rst_n        =   1'b0    ; 
       en           =   1'b0    ;
       round_cfg    =   1'b0    ;
       #100
       flout_a      =   32'b01000001001000000000000000000000    ;
       flout_b      =   32'b01000001101000000000000000000000    ;
       en           =   1'b1    ;
       rst_n        =   1'b1    ; 
       #10
       en           =   1'b0    ;
       #20
       
       flout_a      =   32'b01000001001000000000000000000000    ;
       flout_b      =   32'b11000001101000000000000000000000    ;
       en           =   1'b1    ;
       rst_n        =   1'b1    ; 
       #10
       en           =   1'b0    ;
       #10
       $finish  ;
    end
    
    always #5
    begin
        clk =   ~clk    ;
    end

    pipe_float_mul      pipe_float_mul_inst
    (
        .clk                        (clk),// 时钟信号
        .en                         (en),// 使能信号
        .rst_n                      (rst_n),// 复位信号
        .round_cfg                  (round_cfg),// 决定舍入的方法,0采用chopping,1采用就近舍入 
        .flout_a                    (flout_a),// 输入的被乘数
        .flout_b                    (flout_b),// 输入的乘数
        .flout_c                    (flout_c),// 输出运算结果
        .valid_flout_c              (valid_flout_c),
        .overflow                   (overflow) // 输出溢出标志    
    ); 


endmodule
相关推荐
mcupro16 小时前
纯FPGA控制AD9361的思路和实现之一 概述
fpga开发
2202_7544215418 小时前
纯FPGA实现驱动AD9361配置的思路和实现之一 概述
fpga开发
mcupro18 小时前
纯FPGA实现AD9361控制的思路和实现 UART实现AXI_MASTER
fpga开发
建筑玩家19 小时前
FPGA练习———DDS波形发生器
fpga开发
hahaha601620 小时前
ARINC818-实现
网络·fpga开发
杰克逊的日记3 天前
FPGA阵列
fpga开发·集成电路
爱吃羊的老虎3 天前
【verilog】Verilog 工程规范编码模板
fpga开发
爱吃羊的老虎3 天前
【verilog】在同一个 always 块中写了多个“看起来独立”的 if / if-else,到底谁先谁后,怎么执行?会不会冲突?
fpga开发
肯德基疯狂星期四-V我503 天前
【FPGA】【DE2-115】DDS信号发生器设计
fpga开发·de2-115