verilog求倒数-ROM实现方法
采用线性逼近法结合32段线性查找表的方式来实现1/z的计算。
首先将1/32-1/64的定点化数据存放到ROM中,ROM中存放的是扩大了2^20 次方的数字四舍五入后的整数部分。n值越大,精度越大,误差越小。这里取n=20;
ROM中存储的数据是1/(32+i)*2^20的四舍五入的整数部分。
32-64间的数据可以通过查表来实现,其他的数据则采用的是线性逼近的方法。
线性逼近的步骤为:
1.确定最高非零比特位的位置
2.对z进行左移或者右移,得到zp
3.zp查找ROM,得到1/zp,以及1/(zp+1),
4.求的1/zp-1/(zp+1),为误差A
5.N=z-zp*2^(m-5)
6.B=A/2^(m-5)*N
7.将扩大的部分缩小回去,或者缩小了的放大回去,那么1/z=(1/zp-B)*(1/2^(m-5))
代码插入:
module top_inv(
input clk,syn_rst,
input [:]dataa,
input [:]datab,
//input [20:0]ampout,
output reg [:]inv
// output reg done
);
reg [:] address1;
reg [: ]address2;
wire [:] m;
// wire done;
reg [:]invr;
reg [:] ampout_r;
reg [:] ampout_r1;
wire [:] ampout;
reg [:] ampoutr1,ampoutr2,ampoutr3,ampoutr4;
wire [:] inv_r1;
wire [:] inv_r2;
reg [:] diff_r;
reg [:] diffr;
reg [:] diff;
reg [:] N;
reg [:] N1;
reg en; always @(posedge clk or negedge syn_rst)
begin
if(~syn_rst)
begin
ampoutr1<='d0;
ampoutr2<='d0;
ampoutr3<='d0;
ampoutr4<='d0;
end
else
ampoutr1<=ampout;
ampoutr2<=ampoutr1;
ampoutr3<=ampoutr2;
ampoutr4<=ampoutr3;
end
reg [:] inv_r1t1,inv_r1t2,inv_r1t3;
always@(posedge clk or negedge syn_rst)
begin
if(~syn_rst)
begin
inv_r1t1<=;
inv_r1t2<=;
inv_r1t3<=;
end
else
begin
inv_r1t1<=inv_r1;
inv_r1t2<=inv_r1t1;
inv_r1t3<=inv_r1t2;
end
end
reg [:] mt1,mt2,mt3,mt4,mt5;
always@(posedge clk or negedge syn_rst)
begin
if(~syn_rst)
begin
mt1<=;
mt2<=;
mt3<=;
mt4<=;
mt5<=;
end
else
begin
mt1<=m;
mt2<=mt1;
mt3<=mt2;
mt4<=mt3;
mt5<=mt4;
end
end
reg sel;
reg selr1,selr2;
always @(posedge clk or negedge syn_rst)
begin
if(~syn_rst)
begin
diff<=;
diffr <= ;
ampout_r<='b0;
ampout_r1<=;
address1<='b0;
address2<='b0;
en<=;
sel<=;
end
else
begin
// if(done)
//begin
if((ampout>=)&&(ampout<=))
begin
ampout_r<=;
ampout_r1<=;
address1<=ampoutr3-;
address2<= ;
diff <= ;
diffr <= ;
N <= ;
N1<= ;
en<=;//不需要计算m的值
sel<=;
selr1<=;
selr2<=;
end
else
begin
en<=;//需要计算m的值
if(m>)
begin
// ampoutrr<=ampout;
ampout_r<=ampoutr1>>(m-);
ampout_r1<=ampout_r;//zp
address1<=ampout_r-;///inv_r1
address2<=ampout_r-;///inv_r2
diff <= inv_r1-inv_r2;
diffr <=diff;
N1<=ampout_r1<<(mt2-);
N<=ampoutr4-N1;
selr1<=;
selr2 <= selr1;
sel <= selr2;
end
if(m<)
begin
//ampoutrr<=ampout;
ampout_r<=ampoutr1<<(-m);// mt4 mt3 mt2
ampout_r1 <= ampout_r;// N N1 ampout_r1
address1<=ampout_r-;///mt4 inv_r1
address2<=ampout_r-;//inv_r1t3 inv_r2 mt1
diff <= inv_r1-inv_r2;//diff_r<<diffr<<diff<<address<<ampout_r<< m <<ampout
diffr <=diff; // ampoutr3 ampoutr2 ampoutr1
N1<=ampout_r1>>(-mt2);
N<=ampoutr4-N1;
selr1<=;
selr2 <= selr1;
sel <= selr2;
end
end
end
// end
end
// assign diff=sel?(inv_r1-inv_r2):'b0;
//assign N=sel?(ampout-N1):0;
//assign diff_r = en?(diff*N>>(m-5)):0;
//assign diff_r = (m>5)?(diff*N>>(m-5)):(diff*N<<(5-m));
// assign inv = sel?(inv_r1-diff_r)>>(m-5):inv_r1; always@(posedge clk or negedge syn_rst)
begin
if(~syn_rst)
begin
invr<=;
// done<=0;
diff_r<=;
end
else
begin
if(sel) begin if(m>)begin
diff_r <= diffr*N>>(mt4-);
invr<=(inv_r1t3-diff_r)>>(mt5-);
// done<=1;
end
else begin
diff_r <= diffr*N<<(-mt4);
invr<=(inv_r1t3-diff_r)<<(-mt5);
// done<=1;
end
end
else
begin
diff_r<=;
invr<=inv_r1t3;
end
end
end
always@(posedge clk or negedge syn_rst)
begin
if(~syn_rst)
begin
inv<=;
end
else
begin
if(invr)
inv<= invr;
else
inv<=inv;
end
end
//ROM 核的例化 rom u_rom(.clk(clk),
.address1(address1),
.address2(address2),
.inv_r1(inv_r1),
.inv_r2(inv_r2)//,
//.c(c)
);
//例化寻找最高非零位
not_0 u_not_0 (
// port map - connection between master ports and signals/registers
.ampout(ampout),
.clk(clk),
.m(m),
.en(en),
.syn_rst(syn_rst)
);
complex_abs u_comlex_abs(
.clk(clk),
.syn_rst(~syn_rst),
.dataa(dataa),
.datab(datab),
.ampout(ampout)
);
endmodule
那么最终的仿真结果:如果直接查询的话,结果输出延时一个时钟周期,如果线性逼近的方法得到,延时3-5个时钟周期,这里周期设定为20ns;

占用资源报告:

增加一个求平方根的模块以后的仿真结果(数据输入后,一共需要约10个时钟周期才可以计算出一个平方更求导数值)。有一个小疑问就是怎么添加一个标志信号,让我们知道哪里输出的inv 信号是有效的

verilog求倒数-ROM实现方法的更多相关文章
- 25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有
package zhongqiuzuoye; //自己写的方法 public class Rect { public double width; public double height; Rect( ...
- C++ 求阶乘 四种方法
来总结下求阶乘的各种方法哈. 写在最前:①各个代码仅仅是提供了求阶乘的思路,以便在实际须要时再来编码,代码并不健壮!②各个程序都在1到10内測试正确. 代码一: #include<iostrea ...
- 表达式求值(二叉树方法/C++语言描述)(二)
表达式二叉树节点的数据可能是运算数或运算符,可以使用一个联合体进行存储:同时还需要一个变量来指示存储的是运算数还是运算符,可以采用和栈方法求值中一样的枚举类型TokenType: typedef en ...
- POJ 3450 Corporate Identity (KMP,求公共子串,方法很妙)
http://blog.sina.com.cn/s/blog_74e20d8901010pwp.html我采用的是方法三. 注意:当长度相同时,取字典序最小的. #include <iostre ...
- 以Python列表特性为切入点的求质数列表的方法
一般,构造一个含有2-x之间所有质数的列表,我们采用最简单的遍历判断质数的方法: # 方法一 1 prime = [] def is_prime(n): if n <= 1: return Fa ...
- 表达式求值(二叉树方法/C++语言描述)(三)
二叉树方法求值对运算数处理的方法与栈方法求值不太相同,除了将字符串中的运算数转换为浮点类型外,还需要生成新的节点: void Calculator::dealWithNumber(char *& ...
- 表达式求值(二叉树方法/C++语言描述)(一)
使用二叉树对算数表达式(以下简称为表达式)进行求值,实质上是将表达式转换为二叉树,对其进行后序遍历,得到后缀表达式的同时可以求得表达式的值.转换和求值的过程也需要借助数据结构栈的帮助. 二叉树数据结构 ...
- java求最大值以及定义方法调用
class ArrayDome { public static void main(String[] args) { int[] arr = {-12,-51,-12,-11}; int max = ...
- Haybale Stacking(差分数组 + 求中位数的一些方法 + nth_element)
题意: 给定N个初始值为0的数, 然后给定K个区间修改(区间[l,r] 每个元素加一), 求修改后序列的中位数. 分析: K个离线的区间修改可以使用差分数组(http://www.cnblogs.co ...
随机推荐
- CAR-T|Single cell plan|Extracellular RNA|
生物医疗大数据 安吉丽娜朱莉发现抑癌基因事件,BRCA突变与乳腺癌关联. 个体化测序商品23 and me 多组学数据研究:eg:太空和地球双胞胎发现生化指标差不多. 研究模式和工业模式相结合. 研究 ...
- this 深度面试题3
window.val = 1; var obj = { val: 2, dbl: function () { this.val *= 2; val *= 2; console.log(val); co ...
- 移除手机端a标签点击自动出现的边框和背景
手机端a标签会自动补充出现边框或者背景,使得用户知道a标签的点击状态,但样式很不好看 <!DOCTYPE html> <html> <head> <meta ...
- 阿里云-容器服务之集群服务 k8s(Jenkins+gitlab+k8s的devops)- 01
由于docker官方停止更新Swarm,另外swarm在使用期间出现了很多bug,所以阿里云也在2019年7月发布公告:于2019年12月31日起停止技术支持,请您尽快迁移至容器服务Kubernete ...
- Mybatis学习——初始MyBatis
什么是MyBatis框架? MyBatis框架是一种ORM(既对象关系映射)框架. 什么是ORM框架? 是一种为了解决面向对象与关系数据库之间数据不匹配的技术,它通过描述Java对象和关系数据库表之间 ...
- 03 Mybatis:01.Mybatis课程介绍及环境搭建&&02.Mybatis入门案例
mybatis框架共四天第一天:mybatis入门 mybatis的概述 mybatis的环境搭建 mybatis入门案例 -------------------------------------- ...
- android studio 修改新建EmptyActivity默认布局
https://www.jianshu.com/p/d4f201135097 打开你的Android Sudio安装目录,我的为D:\Program Files\Android\Android Stu ...
- python中os模块的常用方法
1.os模块:os模块在python中包含普遍的操作系统功能,下面列出了一些在os模块中比较有用的部分. os.sep可以取代操作系统特定的路径分隔符.windows下为 “\\” os.name字符 ...
- JavaSE--对象克隆
当拷贝一个变量时,原始变量与拷贝变量引用同一个对象,这就是说,改变一个变量所引用的对象将会对另一个变量产生影响. 如果创建一个对象的新的 copy,他的最初状态与 original 一样,但以后将可以 ...
- CF633H Fibonacci-ish II(莫队+线段树)
温馨提示:本题十分卡常数,我手动开O2才过的.而数据范围不伦不类的n<=30000,常数小的O(n2)居然比O(n√nlogn)跑得快…… 考虑插进去一个元素对答案产生的影响.原本数列为Σa[i ...