1. 开发环境:
    IDE:LIBERO 9.0(ACTEL公司的)
    芯片:AFS600 (BGA256),是混合系列的FPGA
    仿真软件:modelsim atcel 6.5d
    综合软件:synplify pro D-2009.12A
  2. 周末无聊,复习一下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语+拼音

  3. 看一下这个函数的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_wr

    parameter 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 
        end

    always @(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
        end

    always @(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 nothing

    endcase
        end

    endmodule

    `undef STATE_WIDTH

    其实也没有完全按照C版本的(噢,有点说的不准确,其实是C++版本,嘻嘻),因为考虑到通用乘法太耗资源,所以这个插值只是取了这个点周围的4个的平均值而已(是不是有点上当的感觉),其实这样对于一般的图像插值已经够了,效果比那个C版本的相差不多(这个可不是忽悠你们)

  4. 用到的配置文件: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

  5. 仿真测试文件:testbench.v

    // testbench.v

    `include "config.v"
    `timescale 1ns/1ns

    module testbench;
    parameter clk_period=100;//10MHz

    reg 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

  6. 仿真波形图

    (10+20+30+40)/4=25 满意,看起来是不是很幼稚呢其实一个大的系统都是由这些“幼稚”的部分组合起来的

  7. RTL VIEW,不好截大图,看了也白看,不过呢,不看也白不看:
  8. 一些值得关注的综合参数:

    我选择综合时钟是100MHz,可是经过综合得到的评估时钟只是76MHz

    我的芯片有13824个触发器资源可用,该插值模块用720个触发器资源(5%),IO资源有172个,该设计用了130个(76%),RAM有24块,一块也没有用到(唉,被浪费了),当然,用资源多的做开发是好的,最终产品用的时候选合适的就行(减少成本)

  9. 最坏路径:

    看不清吧,又白看了吧。我讲解一下吧,它是由osrc_addr链接起来,就是这家伙闹得我的设计暂时只能综合到76MHz,要优化代码,使系统能在更高的时钟上运行,那么就得把这些最坏路径一条一条优化好(不是叫你删掉啊,出了事别来找我麻烦),关于系统的优化,自己慢慢琢磨去吧,呵呵,经验会造就你的

  10. 总结:
    C语言那么一小段搞定的事,Verilog HDL(还是说个全称吧)用了那么多,精度还不如C函数的(声明:是我这里没有把它写成这样的,不代表它不能),难道这真是在做破事。你要这样认为也没辙,其实中国优化的后的这些模块放在系统中,这些系统就可变成并行的,就算是系统频率比某些CPU的频率低,但是他整体的性能却很容易做到比CPU做某种特定的工作效率高,这就是并行+硬件的魅力,自己慢慢去体会吧
 

verilog版插值的更多相关文章

  1. FPGA中将十进制数在数码管中显示(verilog版)--二进制转换为BCD码

    这周有朋友问怎样在fpga中用数码管来显示一个十进制数,比如1000.每个数码管上显示一位十进制数.如果用高级语言来分离各位,只需要分别对该数做1000,100,10对应的取商和取余即可分离出千百十个 ...

  2. 数字滤波器的MATLAB与FPGA实现--Altera/Verilog版的pdf版,杜勇等编著的书。

    自己在网上找了很久才找到的资源,花了很大的劲,觉得不易,特地分享给大家.本书讲了使用FPGA的Fir IIR IP核与Matlab配合使用生成滤波器的详细使用方法.贴出地址,http://downlo ...

  3. EDA课设-交通灯-Verilog版----FPGA--004

    分得到析四个状态: S1: 主干道(绿灯亮) ,支干道(亮红灯):--40S S1: 主干道 (黄灯亮) ,支干道(亮红灯):--4S S1: 主干道 (亮红灯),支干道(绿灯亮):--20S S1: ...

  4. 常见查找算法之php, js,python版

    常用算法 >>>1. 顺序查找, 也叫线性查找, 它从第一个记录开始, 挨个进行对比, 是最基本的查找技术 javaScript 版顺序查找算法: // 顺序查找(线性查找) 只做找 ...

  5. 基于FPGA的Cordic算法实现

    CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数.双曲线.指数.对数的 ...

  6. 如何用ModelsimSE仿真IP核-以PLL为例

    我们之前介绍了如何使用Modelsim SE进行仿真和利用do文件的仿真方法,但是其中待仿真的模块是我们自己编写的Verilog模块,但是在实际工作中,我们的设计中会经常用到FPGA厂商给我们提供的现 ...

  7. modelsim-altera IP核仿真

    modelsim 仿真fifo时出现 Instantiation of 'scfifo' failed. The design unit was not found. 2012-07-21 13:27 ...

  8. DPSK通信系统的FPGA实现

    之前接触过一些FPGA的相关知识,借着实现一个简单的DPSK系统,顺便复习和记录一下Verilog HDL的简单使用方法.准备直接用一张图展现DPSK的调制解调原理,再按照模块介绍Verilog的实现 ...

  9. 如何高效的编写Verilog HDL——进阶版

    博主之前写过一篇文章来谈论如何高效的编写Verlog HDL——菜鸟版,在其中主要强调了使用Notepad++来编写Verilog HDL语言的便捷性,为什么说是菜鸟版呢,因为对于新手来说,在还没有熟 ...

随机推荐

  1. logstash之Input插件

    1:stdin标准输入和stdout标准输出 首先执行命令: bin/logstash -e 'input { stdin { } } output { stdout { codec   => ...

  2. oracle 数据库优化【转载】

    版权声明:本文为CSDN博主「咫尺的梦想ing」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/u01305 ...

  3. 【2019个推开发者节】亿级日活APP都在用的个推SDK, 现在全部免费!

    1024程序员节来了 双11近了 各路满减.折扣.领券.秒杀.集赞 营销玩法猛于虎,一看优惠两毛五 日常拼命赶"需求" 修"Bug"的开发者们 想找个好用又不贵 ...

  4. tp32-layuicms项目介绍

    项目结构:  项目截图: 登录页 文章列表 码云仓库:https://gitee.com/lim2018/tp32-layuicms

  5. Docker容器技术入门

    独立容器分开的条件: 1.Namespace命名空间 1.主机名和域名,UTS 2.文件系统,mount 3.进程间通信,IPC 4.独立的进程树PID 5.独立的用户User 6.独立的IP地址tc ...

  6. Flask中的request模板渲染Jinja以及Session

    Flask中的request与django相似介绍几个常用的以后用的时候直接查询即可 1.request from flask import request(用之前先引用,与django稍有不同) r ...

  7. PDF to PNG to PDF

    PDF to PNG to PDF PDF 2 PNG step 1, install PyMuPDF pip install pymupdf -i http://mirrors.aliyun.com ...

  8. mysql执行拉链表操作

    拉链表需求: 1.数据量比较大 2.变化的比例和频率比较小,例如客户的住址信息,联系方式等,比如有1千万的用户数据,每天全量存储会存储很多不变的信息,对存储也是浪费,因此可以使用拉链表的算法来节省存储 ...

  9. 旋转数组 空间复杂度为O(1) 的2 种方法 + 1种空间复杂度O(n)

    题目地址 : 旋转数组. 网上好多不是根本就是错的,就是空间复杂度不是真正为1 下面总结一下 方法1 普通方法(空间复杂度不满足要求,但是题目并不会判错,说明他们没用对空间进行校验) ··· publ ...

  10. ssh 多秘钥管理和坑

    概述 很久之前就想研究一下 ssh 的多秘钥管理,今天正好有时间就研究了一下,挺简单的,记录下来,供以后开发时参考,相信对其他人也有用. 参考资料: Git - 生成 SSH公钥 , Linux 下多 ...