verilog float mult

news2025/4/20 14:35:25

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序调用yolo目标检测模型

目录 后端 前端微信小程序 完整代码 后端 利用Flask&#xff0c;调用目标检测模型&#xff0c;后端代码如下。 # flask_yolo.py from flask import Flask, request, jsonify from ultralytics import YOLO from PIL import Imageapp Flask(__name__) model_path best.p…

Flink框架十大应用场景

Flink框架适合应用的场景 1. 流式数据处理 Flink框架最常用的应用场景是流式数据处理。流式数据处理是指对实时数据进行处理,以便及时地做出决策。例如,一个电商网站需要对用户的行为进行实时分析,以便根据用户的兴趣和行为推荐商品。Flink框架可以帮助电商网站实时地处理数…

【android telecom 框架分析 01】【基本介绍 2】【BluetoothPhoneService为何没有源码实现】

1. 背景 我们会在很多资料上看到 BluetoothPhoneService 类&#xff0c;但是我们在实际 aosp 中确找不到具体的实现&#xff0c; 这是为何&#xff1f; 这是一个很好的问题&#xff01;虽然在车载蓝牙电话场景中我们经常提到类似 BluetoothPhoneService 的概念&#xff0c;但…

【Harmony】文本公共接口EditMenuOptions的使用

文章目录 一、EditMenuOptions介绍二、相关接口介绍2.1、editMenuOptions2.2、EditMenuOptionsonCreateMenu函数说明onMenuItemClick函数说明 2.3、TextRange对象说明2.4、TextMenuItem对象说明2.5、TextMenuItemId属性ofequals 三、简单案例 一、EditMenuOptions介绍 EditMen…

《软件设计师》复习笔记(14.1)——面向对象基本概念、分析设计测试

目录 一、面向对象基本概念 对象&#xff08;Object&#xff09; 类&#xff08;Class&#xff09; 抽象&#xff08;Abstraction&#xff09; 封装&#xff08;Encapsulation&#xff09; 继承&#xff08;Inheritance&#xff09; 多态&#xff08;Polymorphism&#…

JS中实现类似sleep、wait、delay的延时功能

前言 编写代码时很多时候需要进行流程化的操作&#xff0c;各个流程间通常需要等待一定时间&#xff0c;这在很多语言中通常可以使用 sleep 、 wait 、 delay 等函数来实现。JavaScript原生并没有类似的功能&#xff0c;想要延时通常就是使用 setTimeout(functionRef, delay) …

Banana Pi BPI-RV2 RISC-V 路由器开发板发售, 全球首款RISC-V路由器

Banana Pi BPI-RV2 开源路由器是矽昌通信和⾹蕉派开源社区&#xff08;Banana Pi &#xff09;合作设计, 联合打造全球首款RISC-V架构路由器开发板。 这是香蕉派开源社区与矽昌通信继BPI-Wifi5 低成本Wifi5 路由器合作之后的又一力作&#xff0c;为全球开发者与商业客户提供基于…

MAUI项目iOS应用以进 App Store 分发

目录 一.通过Visual Studio分发应用1. 登录Apple 开发者帐户到 Visual Studio2.创建分发证书和配置文件3. 分发应用4. 在App Store Connect 中创建应用程序记录5. 如果你想使用mac发布应用 一.通过Visual Studio分发应用 1. 登录Apple 开发者帐户到 Visual Studio 首先我们要…

CentOS 7系统yum报错解决方案(CentOS 7官方EOL问题修复)

摘要 解决CentOS 7因EOL导致的yum update报错问题&#xff0c;通过替换阿里云镜像源恢复软件安装功能&#xff0c;包含详细操作步骤、操作截图、验证方法与备选镜像源&#xff0c;附有安全风险提示。 一、故障现象与原因分析 1.1 典型报错信息 # 执行yum命令时出现&#xff…

解决Windows update服务启动拒绝访问的问题 | wuauserv 注册表拒绝访问的方法

在某些情况下,为了配置系统更新相关服务(例如禁用 Windows 自动更新),我们需要更改注册表中 wuauserv 项的权限。本教程将带你一步步操作,成功获取并修改权限。 修改注册表路径: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv 步骤一:打开注册表编辑…

深入解析 JDK jstack 命令:线程分析的利器

你点赞了吗&#xff1f;你关注了吗&#xff1f;每天分享干货好文。 高并发解决方案与架构设计。 海量数据存储和性能优化。 通用框架/组件设计与封装。 如何设计合适的技术架构&#xff1f; 如何成功转型架构设计与技术管理&#xff1f; 在竞争激烈的大环境下&#xff0c…

【操作系统原理03】处理机调度与死锁

文章目录 大纲一.处理机调度概念与层次0.大纲1.基本概念2.三个层次3.七状态模型4.三层调度都对比与联系 二.进程调度的时机&#xff0c;切换与过程的调度方式0.大纲1.进程调度时机2.调度方式3.进程的切换与过程 三.调度器和闲逛资源1.调度器/调度程序2.闲逛进程 四.调度算法的评…

Quipus,LightRag的Go版本的实现

1 项目简介 奇谱系统当前版本以知识库为核心&#xff0c;基于知识库可以快构建自己的问答系统。知识库的Rag模块的构建算法是参考了LightRag的算法流程的Go版本优化实现&#xff0c;它可以帮助你快速、准确地构建自己的知识库&#xff0c;搭建属于自己的AI智能助手。与当前LLM…

使用 Vite 快速搭建现代化 React 开发环境

1.检查环境 说明&#xff1a;检测环境&#xff0c;node版本为18.20.6。 2.创建命令 说明&#xff1a;创建命令&#xff0c;选择对应的选项。 npm create vitelatest 3.安装依赖 说明&#xff1a;安装相关依赖。 npm i

PG数据库推进医疗AI向量搜索优化路径研究(2025年3月修订版)

PG数据库推进医疗AI向量搜索优化路径研究 一、医疗 AI 向量搜索的发展现状与挑战 1.1 医疗数据特征与检索需求 医疗数据作为推动医疗领域进步与创新的关键要素,具有鲜明且复杂的特征。从多模态角度看,医疗数据涵盖了结构化数据,如患者基本信息、检验检查报告中的数值结果;…

可穿戴经颅多通道直流电刺激产品测试总结

一 概念原理 tDCS 是一种非侵入性的神经调节技术&#xff0c;利用恒定、低强度直流电&#xff08;通常为 0 - 2mA&#xff09;通过电极作用于特定的大脑区域。其工作原理是通过调节神经元的膜电位&#xff0c;来增加或降低神经元兴奋性的特定区域&#xff0c;从而改变大脑运作。…

详解与HTTP服务器相关操作

HTTP 服务器是一种遵循超文本传输协议&#xff08;HTTP&#xff09;的服务器&#xff0c;用于在网络上传输和处理网页及其他相关资源。以下是关于它的详细介绍&#xff1a; 工作原理 HTTP 服务器监听指定端口&#xff08;通常是 80 端口用于 HTTP&#xff0c;443 端口用于 HT…

Moldflow模流分析教程

Moldflow模流分析教程&#xff1a;

计算机网络 3-4 数据链路层(局域网)

4.1 局域网LAN 特点 1.覆盖较小的地理范围 2.较低的时延和误码率 3.局域网内的各节点之间 4.支持单播、广播、多播 分类 关注三要素 &#xff08;出题点&#xff09; ①拓扑结构 ②传输介质 ③介质访问控制方式 硬件架构 4.2 以太网 4.2.1 层次划分 4.2.2 物理层标准…

单片机AIN0、AIN1引脚功能

目录 1. 模拟-数字转换器&#xff08;ADC&#xff09; 2. 交流电源&#xff08;AC&#xff09; 总结 这两部分有什么区别&#xff1f; 在这个电路图中&#xff0c;两个部分分别是模拟-数字转换器&#xff08;ADC&#xff09;和交流电源&#xff08;AC&#xff09;。以下是这…