FPGA_学习_13_方差计算小模块

测距器件APD的性能与器件本身的温度、施加在APD的偏置电压息息相关。 在不同的温度下,APD的偏压对测距性能的影响非常大。 要确定一个合适的APD的偏压Vopt,首先你要知道当前温度下,APD的击穿电压Vbr,一般来讲,Vopt = Vbr – ΔV,ΔV基本是个固定的值。如果要使用算法找到Vbr,通过寻找APD采集信号的噪声方差的剧变点去寻找Vbr是一个不错的方式。 如下图所示,当方差从10以下,突然剧变到45.31,信号噪声方差剧变4倍不止。我们就可以定义此处偏压43.8V为击穿电压Vbr。 那么要在FPGA实现此功能,首先需要在FPGA中实现方差的计算,这也是本文的内容。 这算是脱离例程,第一个本人自己设计的FPGA小模块。

1 CSDN C知道

ChatGPT已经火爆的不行了,猪如何在ChatGPT的风口起飞,这个问题还真是为难。 不过使用ChatGPT倒是不难,CSDN推出了基于ChatGPT的C知道,功能还是比较强大的。我也赶一下时髦,我对C知道问了一个问题:请帮我用Verilog写一个计算方差的算法。

module VarianceCalculator (input clk,input rst,input [N-1:0] data_in,input valid_in,output reg [31:0] variance,output reg valid_out
);reg [N-1:0] sum;reg [N-1:0] square_sum;reg [31:0] mean;reg [31:0] count;always @(posedge clk or posedge rst) beginif (rst) beginsum <= 'b0;square_sum <= 'b0;mean <= 'b0;count <= 'b0;valid_out <= 0;end else if (valid_in) beginsum <= sum + data_in;square_sum <= square_sum + (data_in * data_in);count <= count + 1;if (count == N-1) beginmean <= sum / N;variance <= square_sum / N - (mean * mean);valid_out <= 1;endendendendmodule

 从算法上来讲,计算方差倒不是一个很难的问题,比如用平方的均值减去均值的平方(平方的期望减去期望的平方)。 C知道提供的Verilog代码就是这样算的,是没有问题的。 但直接拿来用,还是存在少许问题。 不过C知道已经很强大了,是很有参考价值的。

2 纯时序逻辑实现 V1.0

我已记不清从哪里接受了一个写Verilog代码的观念,就是:一个时序逻辑(always块),只写一个变量。这样做的好处是,修改调试非常方便,可以根据仿真结果看哪个变量有问题,然后我就专门去修改那个变量对应的时序逻辑。 不过坏处是,它不如全部变量写到一个时序逻辑里面那样,一眼看到算法的全貌。不过,我不管它的坏处是啥,总之这是我接受的观念,也是我后续编写FPGA代码的风格和态度。

下面给出,我用纯时序逻辑写的方差计算FPGA代码。

2.1 Verilog代码

`timescale 1ns / 1psmodule VarCalculatorV1(input   wire            clk             ,input   wire            rst_n           ,input   wire    [7:0]   data_in         ,input   wire            valid_in        ,output  reg     [15:0]  variance        ,output  reg             valid_out
);//==================================================================
//                        Parameter define
//==================================================================
parameter       N = 256;//==================================================================
//                        Internal Signals
//==================================================================
reg     [31:0]  count;
reg     [15:0]  sum;
reg     [31:0]  square_sum;
reg     [7:0]   mean;//----------------------------- valid_out -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginvalid_out <= 1'b0;     endelse if (count == N+1)beginvalid_out <= 1'b1;endelse beginvalid_out <= 1'b0;end
end//----------------------------- variance -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginvariance <= 'd0;     endelse if (valid_in==1'b1 && count >= N+1 )beginvariance <= (square_sum >> 8) - (mean * mean);endelse beginvariance <= 'd0;end
end//----------------------------- count -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) begincount <= 'd0;     endelse if (valid_in==1'b1)beginif (count == N+2) begincount <= 'd0;endelse begincount <= count + 1'b1;endendelse begincount <= 'd0;end
end//----------------------------- sum -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginsum <= 'd0;     endelse if (valid_in==1'b1)beginif (count < N) beginsum <= sum + data_in;endelse if(count == N || count == N+1) beginsum <= sum;endelse if(count == N+2) beginsum <= 'd0;endendelse beginsum <= 'd0;end
end//----------------------------- square_sum -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginsquare_sum <= 'd0;     endelse if (valid_in==1'b1)beginif (count < N) beginsquare_sum <= square_sum + data_in*data_in;endelse if(count == N || count == N+1) beginsquare_sum <= square_sum;endelse if(count == N+2) beginsquare_sum <= 'd0;endendelse beginsquare_sum <= 'd0;end
end//----------------------------- mean -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginmean <= 'd0;     endelse if (valid_in==1'b1)beginif (count >= N) beginmean <= sum >> 8;endelse beginmean  <= 'd0;endendelse beginsum <= 'd0;end
endendmodule

啰嗦几句废话哈,由于需要验证代码的准确性,因此我们对其进行了ModelSim仿真。 本来呢,由于ModelSim的仿真代码我不是很熟悉, 我还不太会使用仿真代码来创建一个我想要的data_in。所以,我在仿真的时候,在用到data_in的地方,我都是用模块内部的计数变量count来代替的。(也就是说,我们计算的是从0~255这256个数的方差)。后来仿真成功确定了代码的准确性之后,我重新去调整我的仿真代码,使得我给到这个模块的data_in变量和模块内部的count变量是一样的。

下面给出对应的ModelSim仿真代码。

2.2 ModelSim仿真代码

`timescale 1ns/1ps
module tb_VarCalculator (); /* this is automatically generated */// clockreg clk;reg rst_n;reg  [7:0] data_in;reg        valid_in;wire [15:0] variance;wire        valid_out;parameter N = 256;VarCalculatorV1 #(.N(N)) inst_VarCalculator (.clk       (clk),.rst_n     (rst_n),.data_in   (data_in),.valid_in  (valid_in),.variance  (variance),.valid_out (valid_out));initial beginclk <= 1'b0;forever #(10) clk = ~clk;endinitial beginrst_n <= 1'b0;#10rst_n <= 1'b1;endinitial beginvalid_in <= 1'b0;#10valid_in <= 1'b1;endreg [15:0] tb_count;initial begintb_count <= 'd0;data_in <= 'd0;#10// 仿真代码中for循环是比较值得后续学习参考的for(tb_count = 1; tb_count <= N+3; tb_count = tb_count + 1) begin#20if(tb_count<='d255) begindata_in <= tb_count; endelse beginif (tb_count=='d258) begintb_count <= 'd0;enddata_in <= 'd0; end                endendendmodule

仿真的时候,有个小技巧,真的好方便,特别提高仿真效率。

2.3 高效仿真小技巧

首先找到如下图所示的仿真编译文件 tb_VarCalculator_compile.do。

 打开这个文件,注释最后一行。

 修改完这个编译文件后, 后续你如果你的仿真代码或者你的功能模块代码有任何的改动,你改了之后先保存。

然后在ModelSim命令行输入三个命令(第一次输入后,后面你用上键↑下键↓就能快速输入了),编译 → 重启 → 运行。

就可以实现快速修改代码仿真。

2.4 仿真结果

 

分析一下仿真结果

1、可以看到仿真代码给出的data_in在0~255部分是和咱们模块内部的count变量一模一样的。仿真代码里面的for循环还是有点东西的,相信以后的仿真肯定可以借鉴。

2、仿真结果5588也是非常接近咱们用MatLAB算的0~255的方差的。 不能完全相等的原因是,我们的数据量个数是2^8,所以我们的除法是用的位移运算实现的。肯定会存在一定的误差。

3、咱们方差的计算结果延迟的3帧,

        1 首先时序逻辑肯定是要延迟1帧的,所以我在求所有数据的和、求所有数据的平方和的时候,就已经延迟了1帧。  

        2 其次,得到所有数据的和之后,我计算了所有数据的均值,这里又延迟了一帧。

        3 最后,在得到所有数据的均值之后,我又求了所有数据的平方和的均值 减去 均值的平方。

因此咱们总共延迟了三帧。 甚至我都担心最后一步在一个时钟周期内算不过来,还能再进行拆分,不过呢,这样延迟更多了,可能变成4帧或者5帧的。

这个很多帧延迟经常让人难以接受,所以我们下面用组合逻辑进行优化。

3 时序逻辑+组合逻辑 V2.0

组合逻辑是没有时钟延迟的。

当我用时序逻辑,求了所有数据的和,以及所有数据的平方和之后(延迟1帧)。

我可以用组合逻辑,就在当前时钟周期,立即得到:均值、均值的平方、平方和的均值、以及用平方和的均值减去均值的平方得到方差。

那么最终得到的方差,也只会延迟1帧。

3.1 Verilog代码

`timescale 1ns / 1psmodule VarCalculator(input   wire            clk      ,input   wire            rst_n    ,input   wire    [7:0]   data_in ,input   wire            valid_in,output  wire    [15:0]  variance,output  reg             valid_out
);//==================================================================
//                        Parameter define
//==================================================================
parameter       N = 256;//==================================================================
//                        Internal Signals
//==================================================================
reg     [31:0]  count;
reg     [15:0]  sum;
reg     [31:0]  square_sum;
wire    [7:0]   mean;
wire    [23:0]  square_mean;
wire    [15:0]  mean_square;assign square_mean = square_sum >> 8;
assign mean_square = mean * mean;
assign variance = ( valid_in==1'b1 && count == N ) ? (square_mean - mean_square) : 'd0;
assign mean = (valid_in==1'b1 && count == N) ? (sum >> 8) : 'd0;//----------------------------- valid_out -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginvalid_out <= 1'b0;     endelse if (count == N-1)beginvalid_out <= 1'b1;endelse beginvalid_out <= 1'b0;end
end//----------------------------- count -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) begincount <= 'd0;     endelse if (valid_in==1'b1)beginif (count == N) begincount <= 'd0;endelse begincount <= count + 1'b1;endendelse begincount <= 'd0;end
end//----------------------------- sum -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginsum <= 'd0;     endelse if (valid_in==1'b1)beginif (count == N) beginsum <= 'd0;                       endelse beginsum <= sum + data_in;endendelse beginsum <= 'd0;end
end//----------------------------- square_sum -----------------------------
always @(posedge clk or negedge rst_n) beginif (rst_n == 1'b0) beginsquare_sum <= 'd0;     endelse if (valid_in==1'b1)beginif (count == N) beginsquare_sum <= 'd0;                     endelse beginsquare_sum <= square_sum + data_in*data_in;endendelse beginsquare_sum <= 'd0;end
endendmodule

3.2 仿真结果

从仿真结果可看出,方差计算仍然正确,但是延迟只有1帧。 另外,其实咱们的verilog代码也要比V1.0版本精简一些。

本文之所得:

                1、ModelSim高效仿真小技巧(其实在前面的博文已经强调过一次,再次强调一遍,真的很高效)

                2、一个时序逻辑模块里面,尽量只给一个变量赋值。

                3、用组合逻辑可以优化时序逻辑的延迟。

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

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

相关文章

【性能优化】MySQL百万数据深度分页优化思路分析

业务场景 一般在项目开发中会有很多的统计数据需要进行上报分析&#xff0c;一般在分析过后会在后台展示出来给运营和产品进行分页查看&#xff0c;最常见的一种就是根据日期进行筛选。这种统计数据随着时间的推移数据量会慢慢的变大&#xff0c;达到百万、千万条数据只是时间问…

FPGA学习——实现任意倍分频器(奇数/偶数倍分频器均可实现)

文章目录 一、分频器二、Verilog实现任意倍分频器2.1、Verilog源码2.2、仿真文件 三、仿真波形图 一、分频器 在FPGA&#xff08;可编程逻辑门阵列&#xff09;中&#xff0c;分频器是一种用于将时钟信号的频率降低的电路或模块。它可以根据输入的时钟信号生成一个较低频率的输…

python+unittest+requests+HTMLRunner搭建接口测试框架,执行用例请求多个不同请求方式的接口

问题描述&#xff1a; 搭建接口测试框架&#xff0c;执行用例请求多个不同请求方式的接口 实现步骤&#xff1a; ① 创建配置文件config.ini&#xff0c;写入部分公用参数&#xff0c;如接口的基本url、测试报告文件路径、测试数据文件路径等配置项 1 [DATABASE] 2 data_add…

Llama2开源大模型的新篇章以及在阿里云的实践

Llama一直被誉为AI社区中最强大的开源大模型。然而&#xff0c;由于开源协议的限制&#xff0c;它一直不能被免费用于商业用途。然而&#xff0c;这一切在7月19日发生了改变&#xff0c;当Meta终于发布了大家期待已久的免费商用版本Llama2。Llama2是一个由Meta AI开发的预训练大…

Redis的9种数据类型与数据持久化

系列文章传送门&#xff1a; 【七天入门数据库】第一天 MySQL的安装部署 【七天入门数据库】第二天 数据库理论基础 【七天入门数据库】第三天 MySQL的库表操作 【七天入门数据库】第四天 数据操作语言DML 一、Redis的9种数据类型的基本操作 &#xff08;一&#xff09;k…

用OpenCV图像处理技巧之白平衡算法(一)

1. 引言 欢迎继续来到我们的图像处理系列&#xff0c;在这里我们将探讨白平衡的关键技术。如果大家曾经拍过一张看起来暗淡、褪色或颜色不自然的照片&#xff0c;那么此时大家就需要了解到白平衡技术的重要性。在本文中&#xff0c;我们将深入探讨白平衡的概念&#xff0c;并探…

idea+springboot+jpa+maven+jquery+mysql进销存管理系统源码

ideaspringbootjpamavenjquerymysql进销存管理系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.首页3.采购订单4.收货入库5. 采购退货6. 商品入库7. 商品出库8. 库存查询9.商品移库10.库存盘点11.销售订单12.发货出库13.销售退货14.商品查询15. 供应商查询16.客户查询…

微信小程序将接口返回的文件流预览导出Excel文件并转发

把接口url替换就可以用了 exportExcel () {wx.request({url: importMyApply, //这个地方是你获取二进制流的接口地址method: POST,responseType: "arraybuffer", //特别注意的是此处是请求文件流必须加上的属性&#xff0c;不然你导出到手机上的时候打不开&#xff…

Jetson Orin Nano 平台适配IMX585 camera驱动调试记录

1. 前言 Jetson Orin Nano Devkit适配imx585 camera 使用argus_camera捕获流,图片是黑色的 用示波器来测量mipi信号,信号正常 Jetpack版本: sensor参数: dts配置: mode0 { /* */ mclk_khz = “24000”; num_lanes = “4”; tegra_sinterface = “serial_c”; ph…

“VCMessage”任务意外失败

从网上查到很多都是说设置这个位置&#xff0c;但是我的已经是对的&#xff0c;还是出现 “VCMessage”任务意外失败这个错误。 又查到一个人说解决方法是更正OutputPath或从父级继承&#xff1a;右键单击项目,然后转到"属性">"链接器">"常规&q…

mac brew安装 node 踩坑日记- n切换node不生效

最近用了一个旧电脑开发&#xff0c;发现里面node管理混乱&#xff0c;有nvm、n和homebrew&#xff0c;导致切换node 切换不了&#xff0c;开发也有莫名其妙的错误。所以我打算重新装一下node&#xff0c;使用n做为管理工具。 1. 删除nvm cd ~ rm -rf .nvm2. 删除n sudo rm -…

GAMS---典型优化模型和算法介绍、GAMS安装和介绍、GAMS程序编写、GAMS程序调试、实际应用算例演示与经验分享

优化分析是很多领域中都要面临的一个重要问题&#xff0c;求解优化问题的一般做法是&#xff1a;建立模型、编写算法、求解计算。常见的问题类型有线性规划、非线性规划、混合整数规划、混合整数非线性规划、二次规划等&#xff0c;优化算法包括人工智能算法和内点法等数学类优…

Vue移动端项目--瑞幸咖啡重构优化

来了客官&#xff0c;好久不见&#xff01; 从年初开始&#xff0c;就有个想法&#xff0c;想着把之前做过的项目重新整理一下。毕竟今时不同往日&#xff0c;从现在的角度去看曾经做过的项目&#xff0c;倒是觉得有很多稚嫩的地方。毕竟无论做什么都是熟能生巧&#xff0c;由浅…

字符串 (2)--- 前缀函数与 KMP 算法

/* https://www.luogu.com.cn/problem/UVA455 最小周期&#xff1a; n - pi[n -1] */ #include <iostream> #include <string> #include <vector> using namespace std; vector<int> prefix_fun(string s) { int len s.length(); /…

深度学习——批标准化Batch Normalization

什么是批标准化&#xff1f; 批标准化&#xff08;Batch Normalization&#xff09;是深度学习中常用的一种技术&#xff0c;旨在加速神经网络的训练过程并提高模型的收敛速度。 批标准化通过在神经网络的每一层中对输入数据进行标准化来实现。具体而言&#xff0c;对于每个输…

Linux基本指令操作

登陆指令&#xff08;云服务器版&#xff09; 当我们获取公网IP地址后&#xff0c;我们就可以打开xshell。 此时会有这样的界面&#xff0c;我们若是想的登陆&#xff0c;则需要输入以下的指令 ssh 用户名公网IP地址 然后会跳出以下的窗口 接着输入密码——密码便是先前定好…

微服务安全简介

​由于其可扩展性、灵活性和敏捷性&#xff0c;微服务架构已经变得越来越受欢迎。然而&#xff0c;随着这种架构的分布和复杂性增加&#xff0c;确保强大的安全措施变得至关重要。微服务的安全性超越了传统的方法&#xff0c;需要采用全面的策略来保护免受不断演变的威胁和漏洞…

Promise 讲解,js知识,es6

文章目录 一、Promise的三种状态1. 初始态pending2. 成功态fulfilled&#xff0c;调用resolve方法3. 失败态rejected&#xff0c;调用reject方法 二、Promise的方法then方法catch方法 三、async和awaitasync 函数await 表达式 四、代码举例帮助理解1、Promise的值通过then方法获…

在vsCode 中执行Electron 项目时,出现中文乱码问题

问题&#xff1a;vscode 中执行Electron 项目时&#xff0c;控制台出现乱码 解决方法&#xff1a; 在 terminal 修改编码格式&#xff1a;65001代表UTF-8&#xff0c;936代表GBK

IC设计从业者必备的宝藏网站!

对于IC设计从业者而言&#xff0c;获取准确的学习资源&#xff0c;行业资讯直观重要&#xff0c;今日我们推荐ic行业专业的宝藏网站&#xff0c;希望对从业者有所帮助。 01-找开源项目的网站 GitHub除了Git代码仓库托管及基本的 Web管理界面以外&#xff0c;还提供了订阅、讨论…