博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(原創) 如何使用Verilog將YCbCr轉RGB? (SOC) (Verilog) (DE2-70)
阅读量:7172 次
发布时间:2019-06-29

本文共 5398 字,大约阅读时间需要 17 分钟。

Abstract

由於不少視訊設備採用的是YCbCr信號(如DVD、DV),但VGA使用的RGB信號,若要將input結果經過影像處理後,output在VGA,就必須將YCbCr信號轉成RGB才可處理。

Introduction

小美阿帥是Lab中碩一的新生,最近正在研究DE2-70 CD中的DE2_70_TV範例,由於DE2-70_TV的input是YCbCr信號,需要轉成RGB信號後才能輸出到VGA,範例中提供了YCbCr2RGB.v提供轉換,小美與阿帥研究了很久,還是不太了解其中的意義,最後決定請教Lab中玩DE2-70很久的無雙學長,想徹底了解其中的奧秘。

『我知道YCbCr轉RGB的公式如下:』

R
=
 
1.164
(Y-
16
) +
1.596
(Cr-
128
)
G
=
 
1.164
(Y-
16
) -
0.391
(Cb-
128
) -
0.813
(Cr-
128
)
B
=
 
1.164
(Y-
16
) +
2.018
(Cb-
128
)

『但整個YCbCr2RGB.v看起來與這個公式差很遠,到底Verilog是怎麼辦到的呢?』小美一臉無助地發問。
YCbCr2RGB.v / Verilog

1 
module
YCbCr2RGB (
2 
 
input
        iCLK,
3 
 
input
        iRESET,
4 
 
input
        iDVAL,
5 
 
input
  [
7
:
0
] iY,
6 
 
input
  [
7
:
0
] iCb,
7 
 
input
  [
7
:
0
] iCr,
8 
 
output
 
reg
   oDVAL,
9 
 
output
[
9
:
0
] Red,
10 
 
output
[
9
:
0
] Green,
11 
 
output
[
9
:
0
] Blue
12 
);
13 
14 
//
Internal Registers/Wires
15 
reg
  [
9
:
0
]  oRed,oGreen,oBlue;
16 
reg
  [
3
:
0
]  oDVAL_d;
17 
reg
  [
19
:
0
] X_OUT,Y_OUT,Z_OUT;
18 
wire
[
26
:
0
] X,Y,Z;
19 
20 
assign
Red  
=
oRed;
21 
assign
Green
=
oGreen;
22 
assign
Blue 
=
oBlue;
23 
24 
always
@(
posedge
iCLK)
begin
25 
 
if
(iRESET)
begin
26 
    oDVAL  
<=
 
0
;
27 
    oDVAL_d
<=
 
0
;
28 
    oRed   
<=
 
0
;
29 
    oGreen 
<=
 
0
;
30 
    oBlue  
<=
 
0
;
31 
 
end
32 
 
else
 
begin
33 
   
//
Red
34 
   
if
(X_OUT[
19
])
35 
      oRed
<=
 
0
;
36 
   
else
 
if
(X_OUT[
18
:
0
]
>
 
1023
)
37 
      oRed
<=
 
1023
;
38 
   
else
39 
      oRed
<=
X_OUT[
9
:
0
];
40 
41 
   
//
Green
42 
   
if
(Y_OUT[
19
])
43 
      oGreen
<=
0
;
44 
   
else
 
if
(Y_OUT[
18
:
0
]
>
 
1023
)
45 
      oGreen
<=
1023
;
46 
   
else
47 
      oGreen
<=
Y_OUT[
9
:
0
];
48 
     
49 
   
//
Blue
50 
   
if
(Z_OUT[
19
])
51 
      oBlue
<=
0
;
52 
   
else
 
if
(Z_OUT[
18
:
0
]
>
 
1023
)
53 
      oBlue
<=
1023
;
54 
   
else
55 
      oBlue
<=
Z_OUT[
9
:
0
];
56 
57 
   
//
Control
58 
    {oDVAL, oDVAL_d}
<=
{oDVAL_d, iDVAL};
59 
 
end
60 
end
61 
62 
always
@(
posedge
iCLK)
begin
63 
 
if
(iRESET)
begin
64 
    X_OUT
<=
 
0
;
65 
    Y_OUT
<=
 
0
;
66 
    Z_OUT
<=
 
0
;
67 
 
end
68 
 
else
 
begin
69 
    X_OUT
<=
( X
-
 
114131
)
>>
7
;
70 
    Y_OUT
<=
( Y
+
 
69370
  )
>>
7
;
71 
    Z_OUT
<=
( Z
-
 
141787
)
>>
7
;
72 
 
end
73 
end
74 
75 
//
Y 596, 0, 817
76 
MAC_3 u0 (
77 
  iY, iCb, iCr,
78 
 
17
'
h00254, 17
'
h00000,
17
'
h00331,
79 
  X, iRESET, iCLK
80 
);
81 
 
82 
//
Cb 596, -200, -416
83 
MAC_3 u1 (
84 
  iY, iCb, iCr,
85 
 
17
'
h00254, 17
'
h3FF38,
17
'
h3FE60,
86 
  Y, iRESET, iCLK
87 
);
88 
89 
//
Cr 596, 1033, 0
90 
MAC_3 u2 (
91 
  iY, iCb, iCr,
92 
 
17
'
h00254, 17
'
h00409,
17
'
h00000,
93 
  Z, iRESET, iCLK
94 
);
95 
96 
endmodule

『對啊!!尤其69行更詭異,114131、69370、141787是怎麼來的?公式裡完全沒出現這3個數字,而且為什麼最後又要 >> 7呢?』阿帥在旁邊也趕緊附和。

69行

X_OUT
<=
( X
-
 
114131
)
>>
7
;
Y_OUT
<=
( Y
+
 
69370
  )
>>
7
;
Z_OUT
<=
( Z
-
 
141787
)
>>
7
;

無雙學長最近正埋首幫教授編寫DE2-70教材與畢業論文,不過看到小美與阿帥的好學,心裡還是非常感動,就打算暫停手邊的工作,先解決學弟妹的問題。

『這個問題很多人問過我,主要是因為YCbCr轉RGB的公式牽涉到浮點運算,在Verilog並不容易實現,所以使用了一些技巧重新推導了整個公式,我在曾經提過這個技巧,當時也有考慮直接拿YCbCr2RGB.v來解講,不過怕這個公式太複雜而模糊了焦點,所以才另外寫了攝氏溫度轉華氏溫度的範例,但在實務上,YCbCr轉RGB應該是最多人第一次遇到浮點運算的機會,趁這個機會,我就把整個module講解一次。』

無雙學長拿了一張紙,準備將公式重新推導一次。

『這是原本YCbCr轉RGB的公式,我們可以發現這需要浮點運算,Verilog雖然有real型別,但只能用在testbench,不能用在RTL。』

R
=
 
1.164
(Y-
16
) +
1.596
(Cr-
128
)
G
=
 
1.164
(Y-
16
) -
0.391
(Cb-
128
) -
0.813
(Cr-
128
)
B
=
 
1.164
(Y-
16
) +
2.018
(Cb-
128
)

『現在將整個算式展開』

R
=
 
1
.164Y                +
1
.596Cr -
222.912
G
=
 
1
.164Y -
0
.391Cb -
0
.813Cr +
135.488
B
=
 
1
.164Y +
2
.018Cb                -
276.928

『因為Verilog無法處理浮點數,所以我們打算使用提到的技巧:將整個算式先放大處理,最後再縮小,現在將算式左右兩邊放大512倍,也就是2^9,相當於<<9。』

R >>
9
 
=
596Y          + 817Cr -
114131
G >>
9
 
=
596Y - 200Cb  - 416Cr +
69370
B >>
9
 
=
596Y + 1033Cb         -
141787

『為什麼要*512呢?不可以乘其他數字嗎?』細心的小美馬上發現問題。

『當然可以,你也可以*1024,也就是<<10,只要最後記得>>10還原就好。』

『114131、69370、141787這些整數都出現了耶,為什麼75行要使用megafunction呢?』阿帥又發現了另外一個問題。

75行

//
Y 596, 0, 817
MAC_3 u0 (
  iY, iCb, iCr,
 
17
'
h00254, 17
'
h00000,
17
'
h00331,
  X, iRESET, iCLK
);
 
//
Cb 596, -200, -416
MAC_3 u1 (
  iY, iCb, iCr,
 
17
'
h00254, 17
'
h3FF38,
17
'
h3FE60,
  Y, iRESET, iCLK
);
//
Cr 596, 1033, 0
MAC_3 u2 (
  iY, iCb, iCr,
 
17
'
h00254, 17
'
h00409,
17
'
h00000,
  Z, iRESET, iCLK
);

『596 * Y + 817 * Cr這種乘加運算,當然也可以自己用Verilog寫,並自己處理pipeline以提高Fmax,DE2-70 CD中的範例有個特色,就是工程師對Altera的megafunction相當的熟悉,CD範例中到處可看到工程師巧妙使用megafunction之處,這裡使用了ALTMULT_ADD做乘加,透過megawizard設定就可自動幫你處理pipeline了。阿帥啊,你也自己用Verilog而不用megafunction寫寫看當練習。』

『69行為什麼要減114131呢?又為什麼要>>7呢?』這是小美原本百思不解之處。

69行

X_OUT
<=
( X
-
 
114131
)
>>
7
;
Y_OUT
<=
( Y
+
 
69370
  )
>>
7
;
Z_OUT
<=
( Z
-
 
141787
)
>>
7
;

『根據新推導的算式:R >> 9 = 596Y + 817Cr - 114131,X已經MAC_3算出來了,所以還要減去114131才行,至於 >> 7,這是個簡略的寫法,我將完整寫法還原,你們就一目了然了』。

X_OUT
<=
(( X
-
 
114131
)
>>
 
9
)
<<
 
2
;
Y_OUT
<=
(( Y
+
 
69370
  )
>>
 
9
)
<<
 
2
;
Z_OUT
<=
(( Z
-
 
141787
)
>>
 
9
)
<<
 
2
;

『原本算式經過 <<9 放大,最後要用 >>9 還原,這很合理,但別忘了output [9:0] Red是10 bit,而input  [7:0] iY是8 bit,所以最後還得放大 <<2 才行,一來一往就變成 >> 7了』。

『啊!!原來是這樣啊!!』小美恍然大悟。

『這樣看起來就很完美了,但為什麼34行還要對output做些判斷呢?』阿帥果然思考敏捷,立刻又提出了新的問題。

34行

//
Red
if
(X_OUT[
19
])
  oRed
<=
 
0
;
else
 
if
(X_OUT[
18
:
0
]
>
 
1023
)
  oRed
<=
 
1023
;
else
  oRed
<=
X_OUT[
9
:
0
];
//
Green
if
(Y_OUT[
19
])
  oGreen
<=
0
;
else
 
if
(Y_OUT[
18
:
0
]
>
 
1023
)
  oGreen
<=
1023
;
else
  oGreen
<=
Y_OUT[
9
:
0
];
     
//
Blue
if
(Z_OUT[
19
])
  oBlue
<=
0
;
else
 
if
(Z_OUT[
18
:
0
]
>
 
1023
)
  oBlue
<=
1023
;
else
  oBlue
<=
Z_OUT[
9
:
0
];

『由於做了放大再縮小的運算,難免會造成overflow的狀況,所以最後多加了判斷,若大於1023,就當1023記,若小於0,就當成0,這樣結果才合理。』

『無雙學長,我還有最後一個問題,為什麼在DE2-70的範例常常看到58行這種寫法,這倒底是什麼意思呢?』這也是小美困惑很久的問題。

58行

//
Control
{oDVAL, oDVAL_d}
<=
{oDVAL_d, iDVAL};

『這是友晶工程師一種技巧的寫法,讓code可以一行完成,看起來比較精簡,學弟妹們可以將這種技巧學起來,事實上它就相當於以下寫法。』

oDVAL_d
<=
iDVAL;
oDVAL  
<=
oDVAL_d;

『因為多了一些運算,所以希望data valid的信號多一個clock做delay,若寫成兩行大家就都能看的懂了。』無雙學長做了以上的解釋。

『謝謝學長,我總算看懂整個module在幹什麼了。』

完整程式碼下載

Conclusion

無雙學長最後做了以下結論:『演算法多多少少都會牽涉到浮點運算,不可能剛剛好都是整數,夠過這個技巧,就能將很多演算法從C語言改用Verilog實現,並配合硬體的parallel、concurrent、pipeline等特性做硬體加速。』

See Also

转载地址:http://axbzm.baihongyu.com/

你可能感兴趣的文章
C++ 模板类的参数推导
查看>>
Cview的派生类
查看>>
Android activity的生命周期
查看>>
HTML5+Css3-webkit-filter
查看>>
css border-bottom(指定下边线的样式、宽度及颜色)
查看>>
Spring框架
查看>>
Aspose.Cells.dll的用法
查看>>
P1352 没有上司的舞会
查看>>
Bzoj 1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐 深搜,bitset
查看>>
关于《淘宝技术这十年》
查看>>
System类
查看>>
某网站html的注释
查看>>
IOS异步获取数据并刷新界面dispatch_async的使用方法
查看>>
macos mojave 安装brew 出错总结
查看>>
HDU 1667 Nested Dolls
查看>>
当程序的后台代码无法调试的时候,检查三个地方
查看>>
SQL数据库类型
查看>>
XGPush集成(信鸽集成)demo
查看>>
结构化异常处理 读书笔记
查看>>
性能优化3--数据库优化
查看>>