当前位置: 首页 > news >正文

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) beginif (!rst_n) begin      //复位,初始化s1        <= 1'b0;exp1      <= 8'b0;man1      <= {1'b1, 23'b0};cnt_delay <=  5'd0    ;endelse beginif( cnt_delay == 5'd5 )begincnt_delay <= 5'd0   ;endelse if( en == 1'b1 )begincnt_delay <=    5'd1    ;endelse if( cnt_delay >= 5'd1 )begincnt_delay   <=  cnt_delay + 1'b1    ;endelse if( cnt_delay == 5'd0 )begincnt_delay   <=  5'd0    ;endelsebegincnt_delay   <=  cnt_delay   ;endif (en == 1'b1 ) begins1   <= flout_a[31];exp1 <= flout_a[30:23];man1 <= {1'b1, flout_a[22:0]};endendend/*---------------提取flout_b 的符号,阶码,尾数---------------------*/
always @(posedge clk or negedge rst_n) beginif (!rst_n) begin      //复位,初始化s2   <= 1'b0;exp2 <= 8'b0;man2 <= {1'b1, 23'b0};endelse if (en) begins2   <= flout_b[31];exp2 <= flout_b[30:23];man2 <= {1'b1, flout_b[22:0]};end
end/*--------------------第一级逻辑运算---------------------------------*/
//符号位
assign one_s_out = s1 ^ s2;   //输入符号异或//尾数相乘
always@(*) beginif (man1 == 24'b10000000000_0000000000000)one_m_out = 48'b0;else if (man2 == 24'b10000000000_0000000000000)one_m_out = 48'b0;elseone_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]};elsetemp2 = {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) beginif (!rst_n) beginone_s_reg <= 1'b0;one_e_reg <= 10'b0;one_m_reg <= 48'b0;endelse beginone_s_reg <= one_s_out;one_e_reg <= one_e_out;one_m_reg <= one_m_out;end
end/*--------------------第二级逻辑运算---------------------------------*/
//尾数规范化及舍入处理,溢出判断
always@(*) beginif (one_m_reg == 48'b0) begin  // 处理特殊值two_m_out =  23'b0;n  =  1'b0;end  else beginif (one_m_reg[47] == 1) beginn  = 1'b1;                    // 左归码为1mul_out_p = one_m_reg >> 1;  // 右移一位endelse beginn   = 1'b0;                  // 左归码为0mul_out_p = one_m_reg;       // 不需要右移endif (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;elsetwo_m_out[22:0] = mul_out_p[45:23];endelse  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,故加上1if (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) beginif (!rst_n) begintwo_s_reg <= 1'b0;two_e_reg <= 8'b0;two_m_reg <= 23'b0;two_f_reg <= 2'b0;endelse 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;endelse begintwo_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@(*) beginflout_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;
endendmodule

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         ;initialbeginclk          =   1'b0    ;rst_n        =   1'b0    ; en           =   1'b0    ;round_cfg    =   1'b0    ;#100flout_a      =   32'b01000001001000000000000000000000    ;flout_b      =   32'b01000001101000000000000000000000    ;en           =   1'b1    ;rst_n        =   1'b1    ; #10en           =   1'b0    ;#20flout_a      =   32'b01000001001000000000000000000000    ;flout_b      =   32'b11000001101000000000000000000000    ;en           =   1'b1    ;rst_n        =   1'b1    ; #10en           =   1'b0    ;#10$finish  ;endalways #5beginclk =   ~clk    ;endpipe_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

相关文章:

  • 详细的PyCharm安装教程
  • Java学习手册:Web 应用架构概述
  • B端APP设计:打破传统限制,为企业开启便捷新通道
  • 电脑 访问 github提示 找不到网页,处理方案
  • 第6章 类文件结构《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》
  • 【机器学习-周总结】-第4周
  • 实用电脑工具,轻松实现定时操作
  • Node.js 创建 HTTP 服务端
  • MACOS 上的 快捷指令怎么用,有哪些分享资源可以用
  • 数据结构——快排和归并排序(非递归)
  • vue2技术练习-开发了一个宠物相关的前端静态商城网站-宠物商城网站
  • FiftyOne 管理数据
  • 使用Java基于Geotools的SLD文件编程式创建与磁盘生成实战
  • LeetCode每日一题4.19
  • YOLO11改进-Backbone-使用MobileMamba替换YOLO backbone 提高检测精度
  • Flutter 弹窗队列管理:实现一个线程安全的通用弹窗队列系统
  • 基于尚硅谷FreeRTOS视频笔记——15—系统配制文件说明与数据规范
  • 考公:数字推理
  • 【NLP 66、实践 ⑰ 基于Agent + Prompt Engineering文章阅读】
  • 你的电脑在开“外卖平台”?——作业管理全解析
  • 天地图新版上线对公众、企业有何用?自然资源部总规张兵详解
  • 湖南平江发生人员溺亡事件,已造成4人死亡
  • 美元指数跌破98关口,人民币对美元即期汇率升值至4月3日来新高
  • 中保协:当前普通型人身保险产品预定利率研究值为2.13%
  • 马上评|与其争论董宇辉该不该获奖,不如多关心文学
  • 神舟二十号全系统合练今日展开