verilog版插值
- 开发环境:
IDE:LIBERO 9.0(ACTEL公司的)
芯片:AFS600 (BGA256),是混合系列的FPGA
仿真软件:modelsim atcel 6.5d
综合软件:synplify pro D-2009.12A - 周末无聊,复习一下VERILOG
参考大学写的一段图像插值的C程序写的,先看看这个简单的插值C函数,水平很烂,别见笑:
YBYTE DealPictrue::ChaZhi_Gray(float x, float y,bool lei)
{
int i=int(y);int j=int(x);
if(((y-i)<5e-2&&(x-j)<5e-2)||i==0||j==0||i==w-1||j==h-1)return gray[i][j];
float e=(x-j)*(gray[i][j+1]-gray[i][j])+gray[i][j];
float f=(x-j)*(gray[i+1][j+1]-gray[i+1][j])+gray[i+1][j];
unsigned char d=unsigned char((y-i)*(f-e)+e);
if(d<0)d=0;
else if(d>255)d=255;
return d;
}其实
if(d<0)d=0;else if(d>255)d=255;
放在那里根本没什么意义,呵呵,遵循原版,让大家看看我大学时候的编程水平,该程序是利用在我的一套图像处理的系统中,最终效果还好(别考虑效率)。还有,本人英语向来不是很好(这是本人的一直在努力要改变的),所以大学的很多程序变量和函数名用的是E语+拼音 - 看一下这个函数的verilog版本:interpolation.v
// interpolation.v
`include "config.v"
`define STATE_WIDTH 4//插值运算
module interpolation(iclk, //系统时钟
irst, //复位信号
ix, //图片像素的X坐标,是一个定点数,
//高`DECIMAL_X_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION位为整数部分
//低`DECIMAL_PRECISION_POSTION-1:0位为小数部分
iy, //图片像素的Y坐标,是一个定点数,
//高`DECIMAL_Y_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION位为整数部分
//低`DECIMAL_PRECISION_POSTION-1:0位为小数部分
isrc_first_addr, //存储图像数据缓冲区的首地址
isrc_dat, //存储图像数据缓冲区的数据线
osrc_addr, //存储图像数据缓冲区的地址线
osrc_rd, //存储图像数据缓冲区的读命令
isrc_busy, //存储图像数据缓冲区的读数据是否有效标志
odir_dat, //经过计算得到的插值数据
obusy //输出的插值数据是否有效
);//idir_first_addr,,odir_addr,odir_wr
//,v_cur_state);
input iclk,irst;
input [`DECIMAL_X_POSTION_WIDTH-1:0] ix;
input [`DECIMAL_Y_POSTION_WIDTH-1:0] iy;
input [`RAM_ADDR_WIDTH-1:0] isrc_first_addr;//,idir_first_addr;input [`IMG_COLOR_WIDTH-1:0] isrc_dat;
input isrc_busy;
output [`RAM_ADDR_WIDTH-1:0] osrc_addr;//,odir_addr;output osrc_rd;
output [`IMG_COLOR_WIDTH-1:0] odir_dat;
//output odir_wr;output obusy;
//output [`STATE_WIDTH-1:0] v_cur_state;
reg [`RAM_ADDR_WIDTH-1:0] osrc_addr,odir_addr;
reg [`IMG_COLOR_WIDTH-1:0] odir_dat;//,dat_buf;reg [1:0] dir_dat_ex;
reg [`STATE_WIDTH-1:0] cur_state,nest_state,willdo;
reg osrc_rd,is_bound,obusy;//,odir_wrparameter st_begin=`STATE_WIDTH'd0,st_check_bound=`STATE_WIDTH'd1,st_loading_data=`STATE_WIDTH'd2,
st_loaded_data=`STATE_WIDTH'd3,st_idle=`STATE_WIDTH'd4,st_output_result=`STATE_WIDTH'd5,
st_load_x0_y0=`STATE_WIDTH'd6,st_load_x1_y0=`STATE_WIDTH'd7,st_load_x1_y1=`STATE_WIDTH'd8,
st_load_x0_y1=`STATE_WIDTH'd9,st_output_result2=`STATE_WIDTH'd10;//assign v_cur_state=cur_state;
always @(posedge iclk or negedge irst)
begin
if(!irst)
begin
cur_state<=st_begin;
end
else begin
cur_state<=nest_state;
end
endalways @(cur_state or isrc_busy or is_bound)
begin
case(cur_state)
st_begin:
nest_state=st_load_x0_y0;
st_load_x0_y0:
begin
nest_state=st_loading_data;
willdo=st_check_bound;
end
st_load_x1_y0:
begin
nest_state=st_loading_data;
willdo=st_load_x1_y1;
end
st_load_x1_y1:
begin
nest_state=st_loading_data;
willdo=st_load_x0_y1;
end
st_load_x0_y1:
begin
nest_state=st_loading_data;
willdo=st_output_result2;
end
st_check_bound:
begin
if(is_bound)
nest_state=st_output_result;
else begin
nest_state=st_load_x1_y0;
end
end
st_loading_data:
if(isrc_busy==1'b0)nest_state=st_loaded_data;
st_loaded_data:
nest_state=willdo;
st_output_result:
nest_state=st_idle;
st_output_result2:
nest_state=st_idle;
default:;
endcase
endalways @(posedge iclk or negedge irst)
begin
if(!irst)
begin
obusy<=1'b1;
is_bound<=0;
dir_dat_ex<=0;
odir_dat<=0;
end
else
case(nest_state)
st_load_x0_y0:
begin
osrc_addr<=isrc_first_addr
+(iy[`DECIMAL_Y_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION]
*`IMG_WIDTH
+ix[`DECIMAL_X_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION]
)<<2;// *`IMG_DATA_WASTE_BYTES;IMG_DATA_WASTE_BYTES=4
end
st_load_x1_y0:
begin
osrc_addr<=osrc_addr+`IMG_DATA_WASTE_BYTES;
end
st_load_x1_y1:
begin
osrc_addr<=osrc_addr+`IMG_WIDTH*`IMG_DATA_WASTE_BYTES;
end
st_load_x0_y1:
begin
osrc_addr<=osrc_addr-`IMG_DATA_WASTE_BYTES;
end
st_check_bound:
begin
if(ix[`DECIMAL_PRECISION_POSTION-1:0]==0
&&(iy[`DECIMAL_PRECISION_POSTION-1:0]==0)
&&(ix[`DECIMAL_X_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION]==0
|| iy[`DECIMAL_Y_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION]==0
|| ix[`DECIMAL_X_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION]==(`IMG_WIDTH-1)
|| iy[`DECIMAL_Y_POSTION_WIDTH-1:`DECIMAL_PRECISION_POSTION]==(`IMG_HEIGHT-1)
)
)
is_bound<=1'b1;
end
st_loading_data:
osrc_rd<=1'b1;
st_loaded_data:
begin
{dir_dat_ex,odir_dat}<=isrc_dat+{dir_dat_ex,odir_dat};
osrc_rd<=1'b0;
end
st_output_result:
begin
obusy<=1'b0;
end
st_output_result2:
begin
obusy<=1'b0;
odir_dat<={dir_dat_ex,odir_dat[`IMG_COLOR_WIDTH-1:2]};
end
default:;//st_idle,do nothingendcase
endendmodule
`undef STATE_WIDTH
其实也没有完全按照C版本的(噢,有点说的不准确,其实是C++版本,嘻嘻),因为考虑到通用乘法太耗资源,所以这个插值只是取了这个点周围的4个的平均值而已(是不是有点上当的感觉),其实这样对于一般的图像插值已经够了,效果比那个C版本的相差不多(这个可不是忽悠你们)
- 用到的配置文件:config.v
// config.v
`ifndef Y_IMAGE_PROCESSING
`define Y_IMAGE_PROCESSING`define IMG_WIDTH_BIT 11
`define IMG_HEIGHT_BIT 10`define IMG_WIDTH `IMG_WIDTH_BIT'd1440
`define IMG_HEIGHT `IMG_HEIGHT_BIT'd900`define IMG_COLOR_WIDTH 5'd24
//32BIT=4*8
`define IMG_DATA_WASTE_BYTES 3'd4
`define DECIMAL_PRECISION_POSTION 4
`define DECIMAL_X_POSTION_WIDTH (`DECIMAL_PRECISION_POSTION+`IMG_WIDTH_BIT)
`define DECIMAL_Y_POSTION_WIDTH (`DECIMAL_PRECISION_POSTION+`IMG_HEIGHT_BIT)
`define RAM_ADDR_WIDTH 25`endif
- 仿真测试文件:testbench.v
// testbench.v
`include "config.v"
`timescale 1ns/1nsmodule testbench;
parameter clk_period=100;//10MHzreg iclk,irst;
reg [`DECIMAL_X_POSTION_WIDTH-1:0] ix;
reg [`DECIMAL_Y_POSTION_WIDTH-1:0] iy;
reg [`RAM_ADDR_WIDTH-1:0] isrc_first_addr;//,idir_first_addr;reg [`IMG_COLOR_WIDTH-1:0] isrc_dat;
reg isrc_busy;
wire [`RAM_ADDR_WIDTH-1:0] osrc_addr;//,odir_addr;wire osrc_rd,obusy;
wire [`IMG_COLOR_WIDTH-1:0] odir_dat;
wire [3:0] cur_state;
always @(iclk) #(clk_period/2.0) iclk<=~iclk;initial
begin
iclk=0;
irst=1;
ix=17'h50;
iy=16'h60;
isrc_first_addr=0;
isrc_dat=24'h0;
isrc_busy=0;
#clk_period irst=0;
#clk_period irst=1;
//#(2*clk_period) isrc_busy=0;
#(20*clk_period) $finish;
end
always @(posedge osrc_rd) isrc_dat=isrc_dat+24'd10;interpolation ip(.iclk(iclk),
.irst(irst),
.ix(ix),
.iy(iy),
.isrc_first_addr(isrc_first_addr),
.isrc_dat(isrc_dat),
.osrc_addr(osrc_addr),
.osrc_rd(osrc_rd),
.isrc_busy(isrc_busy),
.odir_dat(odir_dat),
.obusy(obusy)//,// .v_cur_state(cur_state)
);
endmodule - 仿真波形图
(10+20+30+40)/4=25 满意,看起来是不是很幼稚呢其实一个大的系统都是由这些“幼稚”的部分组合起来的
- RTL VIEW,不好截大图,看了也白看,不过呢,不看也白不看:
- 一些值得关注的综合参数:
我选择综合时钟是100MHz,可是经过综合得到的评估时钟只是76MHz
我的芯片有13824个触发器资源可用,该插值模块用720个触发器资源(5%),IO资源有172个,该设计用了130个(76%),RAM有24块,一块也没有用到(唉,被浪费了),当然,用资源多的做开发是好的,最终产品用的时候选合适的就行(减少成本)
- 最坏路径:
看不清吧,又白看了吧。我讲解一下吧,它是由osrc_addr链接起来,就是这家伙闹得我的设计暂时只能综合到76MHz,要优化代码,使系统能在更高的时钟上运行,那么就得把这些最坏路径一条一条优化好(不是叫你删掉啊,出了事别来找我麻烦),关于系统的优化,自己慢慢琢磨去吧,呵呵,经验会造就你的
- 总结:
C语言那么一小段搞定的事,Verilog HDL(还是说个全称吧)用了那么多,精度还不如C函数的(声明:是我这里没有把它写成这样的,不代表它不能),难道这真是在做破事。你要这样认为也没辙,其实中国优化的后的这些模块放在系统中,这些系统就可变成并行的,就算是系统频率比某些CPU的频率低,但是他整体的性能却很容易做到比CPU做某种特定的工作效率高,这就是并行+硬件的魅力,自己慢慢去体会吧
verilog版插值的更多相关文章
- FPGA中将十进制数在数码管中显示(verilog版)--二进制转换为BCD码
这周有朋友问怎样在fpga中用数码管来显示一个十进制数,比如1000.每个数码管上显示一位十进制数.如果用高级语言来分离各位,只需要分别对该数做1000,100,10对应的取商和取余即可分离出千百十个 ...
- 数字滤波器的MATLAB与FPGA实现--Altera/Verilog版的pdf版,杜勇等编著的书。
自己在网上找了很久才找到的资源,花了很大的劲,觉得不易,特地分享给大家.本书讲了使用FPGA的Fir IIR IP核与Matlab配合使用生成滤波器的详细使用方法.贴出地址,http://downlo ...
- EDA课设-交通灯-Verilog版----FPGA--004
分得到析四个状态: S1: 主干道(绿灯亮) ,支干道(亮红灯):--40S S1: 主干道 (黄灯亮) ,支干道(亮红灯):--4S S1: 主干道 (亮红灯),支干道(绿灯亮):--20S S1: ...
- 常见查找算法之php, js,python版
常用算法 >>>1. 顺序查找, 也叫线性查找, 它从第一个记录开始, 挨个进行对比, 是最基本的查找技术 javaScript 版顺序查找算法: // 顺序查找(线性查找) 只做找 ...
- 基于FPGA的Cordic算法实现
CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数.双曲线.指数.对数的 ...
- 如何用ModelsimSE仿真IP核-以PLL为例
我们之前介绍了如何使用Modelsim SE进行仿真和利用do文件的仿真方法,但是其中待仿真的模块是我们自己编写的Verilog模块,但是在实际工作中,我们的设计中会经常用到FPGA厂商给我们提供的现 ...
- modelsim-altera IP核仿真
modelsim 仿真fifo时出现 Instantiation of 'scfifo' failed. The design unit was not found. 2012-07-21 13:27 ...
- DPSK通信系统的FPGA实现
之前接触过一些FPGA的相关知识,借着实现一个简单的DPSK系统,顺便复习和记录一下Verilog HDL的简单使用方法.准备直接用一张图展现DPSK的调制解调原理,再按照模块介绍Verilog的实现 ...
- 如何高效的编写Verilog HDL——进阶版
博主之前写过一篇文章来谈论如何高效的编写Verlog HDL——菜鸟版,在其中主要强调了使用Notepad++来编写Verilog HDL语言的便捷性,为什么说是菜鸟版呢,因为对于新手来说,在还没有熟 ...
随机推荐
- jQuery file upload里面的_create的调用和_initEventHandlers的调用
首先是jquery.ui.widget.js中_createWidget方法内部调用 this._create(); this._trigger( "create", null, ...
- 4、Shiro之IniRealm以及用户登录认证,角色认证,权限认证
1.我们在项目test文件夹下面新建resourse文件夹并将她设置为资源文件夹: 2.在resourse文件夹下面新建user.ini文件 user.ini文件里面声明一个用户: 先写一个用户标签[ ...
- GET,POST传值总结
GET和POST是什么?HTTP协议中的两种发送请求的方法. HTTP是什么?HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议. 其实,GET和POST本质上两者没有任何区别.他们都是 ...
- 在性能测试时使用nmon进行监控服务器性能
在使用Jmeter进行性能测试,可以使用nmon进行服务器的监控. 一.nmon说明 nmon分为工具包和分析包(nmonanalyser) nmon安装很简单,根据服务器版本,下载相应的版本后,进行 ...
- Application.CreateForm()和TForm.Create()创建的窗体有什么区别么?二者在使用上各有什么技巧?(50分)
https://wedelphi.com/t/135849/ 请详细些,并给出例子.谢谢. Application.CreateForm()创建的第一个可显示的窗体是自动成为主窗体,并且自动显示,并且 ...
- 第十届山东省acm省赛补题(1)
今天第一场个人训练赛的题目有点恐怖啊,我看了半个小时多硬是一道都不会写.我干脆就直接补题去了.... 先补的都是简单题,难题等我这周末慢慢来吧... A Calandar Time Limit: 1 ...
- 精读《What's new in javascript》
1. 引言 本周精读的内容是:Google I/O 19. 2019 年 Google I/O 介绍了一些激动人心的 JS 新特性,这些特性有些已经被主流浏览器实现,并支持 polyfill,有些还在 ...
- 用WebService实现对数据库进行操作(添加+删除+修改)(转)
转自:http://blog.csdn.net/beyondqd/article/details/6703169 表为User,字段有 编号: int id,用户名:string UserName,密 ...
- 将python 2.6 升级到 2.7,及pip安装
由于CentOS6.5 自带python版本为2.6.6,实际中使用的大多为2.7.x版本.于是手动升级. 查看python的版本 #python -VPython 2.6.6 1.下载Python- ...
- yum安装php7
1.安装epel源 yum -y install epel-release yum -y install http://dl.fedoraproject.org/pub/epel/epel-relea ...