FPGA设计思想(持续更新)

一、 流水线设计

  将原本一个时钟周期完成的较大的组合逻辑通过合理的切割后分由多个时钟周期完成。该部分逻辑运行的时钟频率会有明显对的提升,提高系统的性能用面积换速度

  一个流水线设计需要4个步骤完成一个数据的处理过程,那么从有数据输入的第一个时钟周期开始,直到第4个时钟周期处理完第一个数据,但在以后的每一个时钟周期都会有处理完成的数据输出,流水线设计在开始处理时需要一定的处理时间,但以后就会不断的输出数据,从而大大提高处理速度。(面积换速度)如果不采用流水线设计,那么处理一个数据就需要4个时钟周期,而采用流水线设计则能够提高将近4倍的处理速度,用一个复杂的算术式子举例,这是官方给的RGB888 to YCbCr的算法公式,我们可以直接把算法移植到FPGA上,但是我们都知道FPGA无法进行浮点运算,所以我们采取将整个式子右端先都扩大256倍,然后再右移8位,这样就得到了FPGA擅长的乘法运算和加法运算了。

  这个计算式子看起来是十分简单的,但是要是直接用Verilog直接写出来,那么只能说,这个人的代码写的一塌糊涂,所以这里就引出FPGA中流水线的设计思想。在这里我们选择加3级流水线,就第一个Y分量而言,先计算括号中得乘法运算,消耗一个时钟,然后将括号中的数据求和,消耗一个时钟,这里为了计算方便,将128也扩大256倍,放到括号中,最终结果除以256就行了也就是右移8位,在FPGA中我们只需要舍弃低8位取高8位就行。具体代码如下

 1 //--------------------------------------------
 2 /*Refer to <OV7725 Camera Module Software Applicaton Note> page 5
 3     Y     =    (77 *R     +     150*G     +     29 *B)>>8
 4     Cb     =    (-43*R    -     85 *G    +     128*B)>>8 + 128
 5     Cr     =    (128*R     -    107*G      -    21 *B)>>8 + 128
 6 --->
 7     Y     =    (77 *R     +     150*G     +     29 *B)>>8
 8     Cb     =    (-43*R    -     85 *G    +     128*B + 32768)>>8
 9     Cr     =    (128*R     -    107*G      -    21 *B + 32768)>>8*/
10 //--------------------------------------------
11 //RGB888 to YCrCb
12 //step1 conmuse 1clk
13 reg     [15:0]    cmos_R1, cmos_R2, cmos_R3;
14 reg     [15:0]    cmos_G1, cmos_G2, cmos_G3;
15 reg     [15:0]    cmos_B1, cmos_B2, cmos_B3;
16 always @(posedge clk or negedge rst_n)
17 begin
18     if(!rst_n)begin
19             cmos_R1 <= 16'd0;
20             cmos_G1 <= 16'd0;
21             cmos_B1 <= 16'd0;
22             cmos_R2 <= 16'd0;
23             cmos_G2 <= 16'd0;
24             cmos_B2 <= 16'd0;
25             cmos_R3 <= 16'd0;
26             cmos_G3 <= 16'd0;
27             cmos_B3 <= 16'd0;
28     end
29     else begin
30         cmos_R1 <= cmos_R0 * 8'd77;
31         cmos_G1 <= cmos_G0 * 8'd150;
32         cmos_B1 <= cmos_B0 * 8'd29; 
33         cmos_R2 <= cmos_R0 * 8'd43; 
34         cmos_G2 <= cmos_G0 * 8'd85; 
35         cmos_B2 <= cmos_B0 * 8'd128; 
36       cmos_R3 <= cmos_R0 * 8'd128;
37       cmos_G3 <= cmos_G0 * 8'd107;
38       cmos_B3 <= cmos_B0 * 8'd21;
39     end
40 end
41 
42 //-----------------------------------------------
43 //step2 consume 1clk
44 reg    [15:0]    img_Y0;
45 reg     [15:0]    img_Cb0;
46 reg     [15:0]    img_Cr0;
47 
48 always @(posedge clk or negedge rst_n)
49 begin
50     if(!rst_n)begin
51         img_Y0 <= 16'd0;
52         img_Cb0 <= 16'd0;
53         img_Cr0 <= 16'd0;
54     end
55     else begin
56         img_Y0  <= cmos_R1 + cmos_G1 + cmos_B1;
57         img_Cb0 <= cmos_B2 - cmos_R2 - cmos_G2 + 16'd32768;
58         img_Cr0 <= cmos_R3 - cmos_G3 - cmos_B3 + 16'd32768;
59     end
60     
61 end
62 //-------------------------------------------
63 //step3 conmuse 1clk
64 reg    [7:0]    img_Y1;
65 reg     [7:0]    img_Cb1;
66 reg     [7:0]    img_Cr1;
67 
68 always @(posedge clk or negedge rst_n)
69 begin
70     if(!rst_n)begin
71         img_Y1  <= 8'd0;
72         img_Cb1 <= 8'd0;
73         img_Cr1 <= 8'd0;
74     end
75     else begin
76         img_Y1  <= img_Y0  [15:8];
77         img_Cb1 <= img_Cb0 [15:8];
78         img_Cr1 <= img_Cr0 [15:8];
79     end
80     
81 end            

流水线

  RGB转YCbCr算法的仿真过程,从图中可以看出,加了流水线后的运算过程,每一级运算相差一个时钟,然而每一级都在进行新的运算,我们加了3级流水线,这样运算速度可以提升3倍。

二、 跨时钟域处理

有三种方法

  1. 打两拍
  2. 异步双口RAM
  3. 格雷码转换

1. 打两拍方法

  在进行uart串口通信的学习的过程中,遇到一个不理解的问题,在接收模块中,小梅哥采取的设计方式是接收进行一步同步化处理,那么为什么要进行同步化处理呢?串口通信的设计,接收的波特率一般是发送波特率的16倍,单bit传输,我的理解是,在发送波特率下的串口数据传输到接收波特率下时,这个过程是跨时钟的,对于小工程而言,不进行同步处理貌似没有什么关系,但是当工程对精度的要求比较强,外界干扰比较大的情况下,我们就必须进行同步化处理,下面我将学习第一种针对单bit的跨时钟域处理方法:打两拍。打两拍的方式,其实就是定义两级寄存器对数据进行延拍。

  如上图,第一个时钟域将数据发送过来后,在第二个时钟域里用两个D触发器把接收数据进行延拍,中间没有任何组合逻辑。

  为什么是进行两级延拍呢?从上面的时序图可以看出,data是第一个时钟域的数据,Q1,Q2是第二个时钟域的触发器,在同一个clk时钟下,假设当clk的上升沿来临时,刚好采集到的数据是data的跳变沿(因为数据在有0变为1的时候,显然不是垂直上去的,它有一个建立时间,所以clk的上升沿采集到跳变沿的情况是完全有可能的),这样的话Q1接收的数据会处于亚稳态,但是我们至少可以保证,在clk下一个上升沿,data是稳定的,Q1基本上可以满足第二级寄存器的保持时间和建立时间的要求,出现亚稳态的几率会得到很大的改善。如果多加寄存器进行延拍,只是对Q2的数据进行了延拍,并没有什么意义,所以,我们选择进行两级延拍来处理单bit数据的跨时钟域处理。

三、 一个让我纠结了几个月问题

一个让我纠结了几个月问题

Altera的板子按键按下去时0.不按下去是1,

Altera的板子按键按下去时0.不按下去是1,

Altera的板子按键按下去时0.不按下去是1,

重要的纠结说三遍

Xilinx的板子按下去时1,不按是0

转载请注明出处:NingHeChuan(宁河川)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏落影的专栏

Metal入门教程(六)边界检测

前面的教程既介绍了Metal的图片绘制、三维变换、视频渲染,也引入MetalPerformanceShaders处理摄像头数据以及用计算管道实现灰度计算,这次尝...

724
来自专栏娱乐心理测试

关于JS的浮点数计算精度问题解决方案

由于接触JS不久,关于JS的浮点数的计算更是之前没有用过,这次写JS项目发现的这个问题:0.1+0.2=0.3000000000004,为什么会出现这么奇怪的问...

913
来自专栏利炳根的专栏

学习笔记CB001:NLTK库、语料库、词概率、双连词、词典

聊天机器人知识主要是自然语言处理。包括语言分析和理解、语言生成、机器学习、人机对话、信息检索、信息传输与信息存储、文本分类、自动文摘、数学方法、语言资源、系统评...

24210
来自专栏CSDN技术头条

大数据并行计算利器之MPI/OpenMP

1 背景 图像连通域标记算法是从一幅栅格图像(通常为二值图像)中,将互相邻接(4邻接或8邻接)的具有非背景值的像素集合提取出来,为不同的连通域填入数字标记,并且...

2236
来自专栏携程技术中心

干货 | ElasticSearch相关性打分机制

作者简介 孙咸伟,后端开发一枚,在携程技术中心市场营销研发部负责“携程运动”项目的开发和维护。 携程运动是携程旗下新业务,主要给用户提供羽毛球、游泳等运动项目的...

6968
来自专栏北京马哥教育

隐马尔科夫模型 python 实现简单拼音输入法

在网上看到一篇关于隐马尔科夫模型的介绍,觉得简直不能再神奇,又在网上找到大神的一篇关于如何用隐马尔可夫模型实现中文拼音输入的博客(http://sobuhu....

3607
来自专栏大数据挖掘DT机器学习

使用TextRank算法为文本生成关键字和摘要

TextRank算法基于PageRank,用于为文本生成关键字和摘要。 目录[-] PageRank 使用TextRank提取关键字 使用TextRank提取关...

3725
来自专栏数据科学与人工智能

【算法】TextRank算法为文本生成关键字和摘要

TextRank算法基于PageRank,用于为文本生成关键字和摘要。其论文是:

702
来自专栏数据结构与算法

二项式定理

其实二项式定理也就一句话:$(x + y)^n = \sum_{i = 0}^n C_{n}^i x^{n - i} y^{i}$

321
来自专栏Spark学习技巧

SparkMLlib的数据类型讲解

SparkMLlib的数据类型讲解 Mllib支持单机上存储的本地向量和矩阵,也支持由一个或者多个RDD支持的分布式矩阵。本地向量和本地矩阵是简单的数据模型,用...

2297

扫码关注云+社区