当前位置: 首页 > 编程学习 > 其它语言 > Verilog > 正文

FPGA设计思想

2018-04-23 来源:博客园/NingHeChuan

一、 流水线设计

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

一个流水线设计需要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倍。