Verilog写一个对数计算模块Log2(x)
网上一个能用的也没有,自己写一个把。
1.计算原理:
整数部分
网上找到了一个c语言的计算方法如下:
int flog2(float x) {return ((unsigned&)x>>23&255)-127; }
用matlab测试了一下,得到的结果是一个log2的整数部分
小数部分
发现小数部分其实都是 1+一个小数 ,然后这个小数值其实可通过最高位是0.5 然后0.25,0.125.......这样累加得到。
比如:
100 0000 0000 0000 0000 0000 -> 1+0.5
110 0000 0000 0000 0000 0000 -> 1+0.5+0.25
这样我只要算出这个然后查表就好了。由于对精度要求不高,只取六位数字进行查表,matlab获取表值的仿真程序如下:
for i = 0:31temp = i/32;templog = log2(1+temp);fprintf('the value of log is%6.2f\n',templog) end
至此,小数部分和整数部分就都得到了。
2.开始写Verilog:
电路结构:
Verilog代码
其中用了3个IP核,包括ROM、定点转浮点单元、浮点加法单元,不做详述
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 10:20:43 03/29/2019 // Design Name: // Module Name: log2fun // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module log2fun(input clk,input dataclk,input rst_n,input data_enable,input [31:0] log_input,output [31:0] log_output);reg [7:0] exp_data; reg [31:0] fix_data; reg fix_enable; wire [31:0] float_exp; wire float_enable;wire [31:0] point_float; reg [4:0] point_addr; wire [4:0] point_addwire;wire result_enable; //reg [31:0] Mem [3:0]; reg [31:0] fifo_data1; reg [31:0] fifo_data2;reg sign_flag;always @(posedge clk or posedge rst_n) beginif(!rst_n) begin exp_data <= 8'd127;sign_flag <= 1'd0;endelse begin //fix_data <= log_input[30:23] > exp_data ? log_input[30:23]-exp_data:exp_data-log_input[30:23];fix_data <= log_input[30:23] - exp_data;point_addr <= log_input[22:18];end endalways @(posedge dataclk or posedge rst_n) beginif(!rst_n) begin fifo_data2 <= 2'd0;fifo_data1 <= 2'd1;endelse begin if(data_enable)begin//Mem[fifo_addr1] <= point_float;//point_floatDelay <= Mem[fifo_addr2];fifo_data1 <= point_float;fifo_data2 <= fifo_data1;endend endassign point_addwire = point_addr;int2float INTCONVERT(.aclk(clk), .s_axis_a_tvalid(data_enable), .m_axis_result_tvalid(float_enable), .s_axis_a_tdata(fix_data), .m_axis_result_tdata(float_exp));log_sheet LOG_DATA (.clka (clk), .addra(point_addwire), .douta(point_float));float_add ADD_FLOAT (.aclk(clk), .s_axis_a_tvalid(float_enable), .s_axis_b_tvalid(float_enable), //.s_axis_a_tready(s_axis_a_tready), //.s_axis_b_tready(s_axis_b_tready), .m_axis_result_tvalid(result_enable), .s_axis_a_tdata(float_exp), .s_axis_b_tdata(fifo_data1), .m_axis_result_tdata(log_output)); endmodule
testbench
`timescale 1ns / 1ps//// // Company: // Engineer: // // Create Date: 10:39:38 03/29/2019 // Design Name: log2fun // Module Name: C:/Users/ray5w/OneDrive/benchmark/code/verylog_vad/verylog_vad/log2fun_tb.v // Project Name: verylog_vad // Target Device: // Tool versions: // Description: // // Verilog Test Fixture created by ISE for module: log2fun // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////module log2fun_tb;// Outputsreg clk;reg dataclk;reg rst;reg data_enable;reg [31:0] din;wire [31:0] dout;// Instantiate the Unit Under Test (UUT) log2fun uut (.clk(clk),.dataclk(dataclk),.rst_n(rst),.log_input(din),.data_enable(data_enable),.log_output(dout));initial begindata_enable <= 1'b0; rst <= 1'b1; din <= 32'b0;#20rst <= 1'b0; #100 rst <= 1'b1; data_enable <= 1'b1; din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25#50din <= 32'h3d23d70a; //0.4#50din <= 32'h3e800000; //0.25 // Add stimulus hereendinitial begin clk = 1;forever#5 clk = !clk;end initial begindataclk = 1;#15 dataclk = 0;forever#25 dataclk = !dataclk;end endmodule
一个c代码方便进行浮点核定点转换的,用来看看最终结果是不是对的:
#include <stdio.h> int float2int(float data); int flog2(float x); float int2float(int data); float datasheet[] = {0.00, 0.04, 0.09, 0.13, 0.17, 0.21, 0.25, 0.29, 0.32, 0.36, 0.39, 0.43, 0.46, 0.49, 0.52, 0.55, 0.58, 0.61, 0.64, 0.67, 0.70, 0.73, 0.75, 0.78, 0.81, 0.83, 0.86, 0.88, 0.91, 0.93, 0.95, 0.98 }; int main(void) { int i ;/*for(i=0;i<32;i++){printf("%x,\n",float2int(datasheet[i]));}*/printf("%d,\n",flog2(0.04));printf("%d,\n",flog2(0.25));printf("%f,\n",int2float(0x40a00000));return 0; } float int2float(int data){float *idata ; int idata2 = data;idata =(float*)&idata2;return *idata; }int float2int(float data){int *idata ; float idata2 = data;idata =(int*)&idata2;return *idata; }int flog2(float x){return ((unsigned&)x>>23&255)-127; }
仅用作思路参考,我是Verilog菜鸟。
下面是实验结果:
matlab验证一下,(3d23d70a就是0.04,输出的e095c28f是-4.68)
有一定误差,要提高精度只要查表那一步增大rom多存点就好了吧
转载于:https://www.cnblogs.com/ray5wang/p/10620056.html
Verilog写一个对数计算模块Log2(x)相关推荐
- 怎么样写一个 node.js模块以及NPM Package
你来到了写一个mode.js模块的舞台中央,不管你是因为自己需要写一个你自己的nodejs模块,还是你仅仅是处于好奇.无论是什么原因,在这个教程里,我将给你演示怎样创建一个nodejs模块. node ...
- 用Python写一个纪念日计算工具
用python写一个纪念日计算工具 前言 主要内容 日期计算函数 GUI布局 用pyinstaller打包生成.exe文件 打包后的.exe文件预览 运行结果 最后提前祝马英俊生日快乐吧~ 前言 纪念 ...
- JavaDay03.练习1.写一个程序,计算KFC饮料第二杯半价策略
写一个程序,计算KFC饮料第二杯半价策略 输入饮料的单价和购买杯数,然后得出需要花费多少钱? (半价策略即偶数杯都是半价的) import java.util.Scanner;/** * 写一个程序, ...
- OpenCV2.3的cvCalcHist函数有问题?255级值总为0,索性自己写一个直方图计算函数,附源码
图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 我在写直方图规定化的代码过程中,发现OpenCV ...
- 用Verilog写一个74LS160
5-10 用Verilog设计一个功能类似74ls160的计数器. (1)解题思路 设计一个74ls160,需要知道它的功能表,以及原理图 (2)核心模块代码 module fidv1 (rd,clk ...
- 【FPGA_001】用Verilog写一个数组,会耗费很多资源
不要在代码里用HDL语言去写一个数组,像下面这样 注:行前的语句意思是,告诉编译器强制将此ram类推综合成分布式ram,将这句话注释掉,综合出来也是同样的结果. 综合后,生成电路图如下,看那密密麻麻, ...
- 用python写一个纪念日计算工具!有对象的特别注意了!
前言 纪念日计算工具 是在了解GUI的规程中,突发奇想写的一个小东西,用到的是Python的 tkinter 控件.本人非开发人员,渣渣数据分析师,如遇大佬请轻喷,如有代码错误或不规范,感谢指正. 主 ...
- 计算机符串长度的函数,用js写一个函数,计算出字符串的长度
// GBK字符集实际长度计算function getStrLeng(str){ var realLength = 0; var len = str.length; var charCode = -1 ...
- Python写一个股价计算的脚本
股价计算脚本 1. 常量计算方法 首先我们定义三个常量,分别是:公司名.股票代码.当前股价 随后在字符串前面加上 f 就可以进行快速格式化,不需要考虑数据类型,但是不能进行精度的控制,进行快速占位符输 ...
- cmd脚本写一个小学生计算习题
2019独角兽企业重金招聘Python工程师标准>>> @echo off echo 输入你的名字回车(Enter键)一次 Set/p "name=你的名字:" ...
最新文章
- 行人被遮挡问题怎么破?百度提出PGFA新方法,发布Occluded-DukeMTMC大型数据集 | ICCV 2019...
- 浅谈分布式消息技术 Kafka--大数据技术栈05
- shardingjdbc每月分表_shardingjdbc分库分表测试
- spring boot 使用swagger
- leetcode1504. 统计全 1 子矩形(动态规划)
- PHP 读取 QQ ip纯真数据库 详解
- python列表元素下标是什么_python列表中元素插入位置总结
- 自适应谱线增强matlab,自适应谱线增强器.doc
- 并发编程(读书笔记)
- loadrunner性能测试——第一步 录制脚本(中文版)
- 最新nodejs的开发学习实战(1)从一个博客开始
- 新手SEO优化原创与伪原创
- 【知识兔】Ctrl+H,Word文档中超好用的快捷键
- Spring源码解析-bean实例化
- Joel Spolsky对计算机学生的建议
- 推荐系统9---AFM与DIN模型(推荐系统遇上注意力机制)
- java 交流群 14187321 欢迎java爱好者参与
- 什么是IPX/SPX
- FastReport for Delphi2010 中文菜单显示不全或者乱码解决方法
- 修改macOS中程序坞的位置和图标大小