色度空間変換CSC(RGB変換YCBCR)の統合可能verilogコード記述
12385 ワード
転載は出所を明記してください.
色度空間はRGB空間をYCrCbに変換し、以下の式で変換を実現する.
Y = (0.299R + 0.587G + 0.114B);
Cr = (0.511R - 0.428G - 0.083B) + 128;
Cb = (-0.172R - 0.339G + 0.511B) + 128;
1、10組のRGB値をテストベクトル(ファイル名:rgb_in.file)として定義し、matlabプログラムを作成して以上の式でYCrCb値に変換する.
2、総合的なVerilogコードプログラム(ファイル名:rgb_to_ycrcb.v)を作成し、以上の式(純組合せ論理ではなくクロックビートが必要)を実現し、File HeaderとComment情報の追加を要求する.
3、Testbench(ファイル名:tb_rgb_to_ycrcb.v)を作成し、テストベクトルファイル(ファイル名:rgb_in.file)からRGBテストベクトル値を読み出し、生成したYCrCb値を結果ファイル(ファイル名:ycrcb_out.file)に格納し、同時に波形ファイルtb_を生成するrgb_to_ycrcb.vcd.
4、Verilogシミュレーション後に生成されたYCrCb値とmatlabプログラムで生成されたYCrCb値を比較し、一致するかどうかを確認し、一致しない場合は原因を分析してください.
5、ModelSimとNCVerilogツールをそれぞれ用いてシミュレーションを行い、送信元コードと波形図を印刷することを要求し、波形図の中でYCrCb値を生成するには整列すべきである(すなわち、同じRGB値の変換に対応して、同じクロックClockで生成すべきである;整列していない場合、データ遅延を採用する.
プログラムコード1. rgb_in.txt
2. rgb_to_ycbcr.v
1.Modelsimシミュレーション波形図
2.Nc-verilogシミュレーション波形図
まとめ
1.本コードは統合可能なコード方式で記述されているため、コードの長さが長く、例えば加算時に2つの数だけ加算し、シフト方式で乗算を実現し、後で乗算器を用いて改善することができる.
2.本コードは色度空間変換の任務を完全に実現し、総合的なコードであり、最後に出力されたYCBCR信号は入力されたRGB信号より6クロック遅延し、3つの出力信号は整列を実現する.
3.本コードの作成により、ファイルからデータを読み取り、ファイルに出力するプロセスを熟知しています.
4.シフトによる乗算の実現の考え方を熟知しており,以降のコード作成に啓発的である.
色度空間はRGB空間をYCrCbに変換し、以下の式で変換を実現する.
Y = (0.299R + 0.587G + 0.114B);
Cr = (0.511R - 0.428G - 0.083B) + 128;
Cb = (-0.172R - 0.339G + 0.511B) + 128;
1、10組のRGB値をテストベクトル(ファイル名:rgb_in.file)として定義し、matlabプログラムを作成して以上の式でYCrCb値に変換する.
2、総合的なVerilogコードプログラム(ファイル名:rgb_to_ycrcb.v)を作成し、以上の式(純組合せ論理ではなくクロックビートが必要)を実現し、File HeaderとComment情報の追加を要求する.
3、Testbench(ファイル名:tb_rgb_to_ycrcb.v)を作成し、テストベクトルファイル(ファイル名:rgb_in.file)からRGBテストベクトル値を読み出し、生成したYCrCb値を結果ファイル(ファイル名:ycrcb_out.file)に格納し、同時に波形ファイルtb_を生成するrgb_to_ycrcb.vcd.
4、Verilogシミュレーション後に生成されたYCrCb値とmatlabプログラムで生成されたYCrCb値を比較し、一致するかどうかを確認し、一致しない場合は原因を分析してください.
5、ModelSimとNCVerilogツールをそれぞれ用いてシミュレーションを行い、送信元コードと波形図を印刷することを要求し、波形図の中でYCrCb値を生成するには整列すべきである(すなわち、同じRGB値の変換に対応して、同じクロックClockで生成すべきである;整列していない場合、データ遅延を採用する.
プログラムコード1. rgb_in.txt
101011011000110101010011
010110110110101111011010
011011011110111000011011
010101011101001000111101
010100010110101101010100
010101000110011010101010
010111011101110001101010
010110101101010101010101
101001000011101010010101
010110101000100110001110
100010001110101010101011
101011100101000111101101
110101011011011100011001
101011100101011000101010
101010111011100001010101
110111010111101110000010
2. rgb_to_ycbcr.v
//************************************************************************//
// Y = (0.299R + 0.587G + 0.114B); //
// Cr = (0.511R - 0.428G - 0.083B) + 128; //
// Cb = (-0.172R - 0.339G + 0.511B) + 128; //
//*************************************************************************//
`timescale 1ns/10ps
module rgb_to_ycbcr(clk,ngreset,R,G,B,Y,Cb,Cr);
input clk,ngreset;
input [7:0] R,G,B;
output[7:0] Y,Cb,Cr;
wire [7:0] Y,Cb,Cr;
/************Y =(1_0011_0010R + 10_0101_1001G + 111_0101B)/1024*************/
reg [16:0] r_256_32;
reg [12:0] r_16_2;
reg [17:0] g_512_64;
reg [12:0] g_16_8;
reg [7:0] g_1;
reg [14:0] b_64_32;
reg [12:0] b_16_4;
reg [7:0] b_1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_256_32<=17'h1ffff;
r_16_2 <=13'h1fff;
g_512_64<=18'h3ffff;
g_16_8 <=13'h1fff;
g_1 <=8'hff;
b_64_32 <=15'h7fff;
b_16_4 <=13'h1fff;
b_1 <=8'hff;
end
else
begin
r_256_32<={R,8'd0}+{R,5'd0} ;
r_16_2 <={R,4'd0}+{R,1'd0} ;
g_512_64<={G,9'd0}+{G,6'd0} ;
g_16_8 <={G,4'd0}+{G,3'd0} ;
g_1 <=G;
b_64_32 <={B,6'd0}+{B,5'd0} ;
b_16_4 <={B,4'd0}+{B,2'd0} ;
b_1 <=B;
end
reg[17:0] r_256_32_16_2;
reg[17:0] g_512_64_16_8;
reg[7:0] g_1_d1;
reg[17:0] b_64_32_16_4;
reg[7:0] b_1_d1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_256_32_16_2<=18'h3ffff;
g_512_64_16_8<=18'h3ffff;
g_1_d1 <=8'hff;
b_64_32_16_4 <=18'h3ffff;
b_1_d1 <=8'hff;
end
else
begin
r_256_32_16_2<=r_256_32+r_16_2;
g_512_64_16_8<=g_512_64+g_16_8;
g_1_d1 <=g_1;
b_64_32_16_4 <=b_64_32+b_16_4;
b_1_d1 <=b_1;
end
reg[17:0] y_r;
reg[17:0] y_g;
reg[17:0] y_b;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
y_r <=18'h3ffff;
y_g <=18'h3ffff;
y_b <=18'h3ffff;
end
else
begin
y_r <=r_256_32_16_2;
y_g <=g_512_64_16_8+g_1_d1;
y_b <=b_64_32_16_4+b_1_d1;
end
reg[17:0] y_rg;
reg[17:0] y_b_d1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
y_rg <=18'h0;
y_b <=18'h0;
end
else
begin
y_rg <=y_r+y_g;
y_b_d1 <=y_b;
end
reg[17:0] y_rgb;
always@(posedge clk or negedge ngreset)
if(!ngreset)
y_rgb<=18'h0;
else
y_rgb<=y_rg+y_b_d1;
wire[7:0] y_tmp;
assign y_tmp=y_rgb[17:10];
/***************Cr = (10_0000_1011R - 1_1011_0110G - 101_0101B)/1024 + 128**************/
reg[17:0] r_512_8;
reg[9:0] r_2_1;
reg[16:0] g_256_128;
reg[13:0] g_32_16;
reg[10:0] g_4_2;
reg[14:0] b_64_16;
reg[10:0] b_4_1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_512_8 <= 18'h1ffff;
r_2_1 <= 10'h3ff;
g_256_128<= 17'h1ffff;
g_32_16 <= 14'h3fff;
g_4_2 <= 11'h7ff;
b_64_16 <= 15'h7fff;
b_4_1 <= 11'h7ff;
end
else
begin
r_512_8 <={R,9'd0}+{R,3'd0} ;
r_2_1 <={R,1'd0}+R;
g_256_128<={G,8'd0}+{G,7'd0} ;
g_32_16 <={G,5'd0}+{G,4'd0} ;
g_4_2 <={G,2'd0}+{G,1'd0} ;
b_64_16 <={B,6'd0}+{B,4'd0} ;
b_4_1 <={B,2'd0}+B;
end
reg[17:0] r_512_8_2_1;
reg[17:0] g_256_128_32_16;
reg[10:0] g_4_2_d1;
reg[17:0] b_64_16_4_1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_512_8_2_1 <=18'h3ffff;
g_256_128_32_16 <=18'h3ffff;
g_4_2_d1 <=11'hff;
b_64_16_4_1 <=18'h3ffff;
end
else
begin
r_512_8_2_1 <= r_512_8+r_2_1;
g_256_128_32_16 <= g_256_128+g_32_16;
g_4_2_d1 <= g_4_2;
b_64_16_4_1 <= b_64_16+b_4_1;
end
reg[17:0] r_512_8_2_1_d1;
reg[17:0] g_256_128_32_16_4_2;
reg[17:0] b_64_16_4_1_d1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_512_8_2_1_d1 <=18'h3ffff;
g_256_128_32_16_4_2<=18'h3ffff;
b_64_16_4_1_d1 <=18'h3ffff;
end
else
begin
r_512_8_2_1_d1 <=r_512_8_2_1;
g_256_128_32_16_4_2<=g_256_128_32_16+g_4_2_d1;
b_64_16_4_1_d1 <=b_64_16_4_1;
end
reg[17:0] cr_r;
reg[17:0] cr_gb;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
cr_r <=18'd0;
cr_gb<=18'd0;
end
else
begin
cr_r <=r_512_8_2_1_d1;
cr_gb<=g_256_128_32_16_4_2+b_64_16_4_1_d1;
end
reg[17:0] cr_rgb;
always@(posedge clk or negedge ngreset)
if(!ngreset)
cr_rgb<=18'h0;
else if(cr_r>cr_gb)
cr_rgb<=cr_r-cr_gb;
else
cr_rgb<=cr_gb-cr_r;
wire[7:0] cr_rgb_d;
assign cr_rgb_d=cr_rgb[17:10];
reg[17:0] cr_r_d1;
reg[17:0] cr_gb_d1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
{cr_r_d1,cr_gb_d1}<=36'h0;
else
{cr_r_d1,cr_gb_d1}<={cr_r,cr_gb};
reg[7:0] cr_tmp;
always@(posedge clk or negedge ngreset)
if(!ngreset)
cr_tmp<=8'd0;
else if(cr_r_d1>cr_gb_d1)
cr_tmp<=8'd128+cr_rgb_d;
else
cr_tmp<=8'd128-cr_rgb_d;
/***********Cb = (-1011_0000R - 1_0101_1011G + 10_0000_1011B)/1024 + 128********/
reg[15:0] r_128_32;
reg[12:0] r_16;
reg[16:0] g_256_64;
reg[9:0] g_2_1;
reg[17:0] b_512_8;
reg[9:0] b_2_1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_128_32<=16'hffff;
r_16 <=13'h1fff;
g_256_64<=17'h1ffff;
g_2_1 <=10'h3ff;
b_512_8 <=18'h3ffff;
b_2_1 <=10'h3ff;
end
else
begin
r_128_32<={R,7'd0}+{R,5'd0} ;
r_16 <={R,4'd0};
g_256_64<={G,8'd0}+{G,6'd0} ;
g_2_1 <={G,1'd0}+G ;
b_512_8 <={B,9'd0}+{B,3'd0} ;
b_2_1 <={B,1'd0}+B ;
end
reg[17:0] r_128_32_16;
reg[17:0] g_256_64_16_8;
reg[9:0] g_2_1_d1;
reg[17:0] b_512_8_2_1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
r_128_32_16 <=18'h3ffff;
g_256_64_16_8<=18'h3ffff;
g_2_1_d1 <=10'h3ff;
b_512_8_2_1 <=18'h3ffff;
end
else
begin
r_128_32_16 <= r_128_32+r_16;
g_256_64_16_8 <= g_256_64+g_16_8;
g_2_1_d1 <= g_2_1;
b_512_8_2_1 <= b_512_8+b_2_1;
end
reg[17:0] cb_r;
reg[17:0] cb_g;
reg[17:0] cb_b;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
cb_r<=18'h3ffff;
cb_g<=18'h3ffff;
cb_b<=18'h3ffff;
end
else
begin
cb_r<=r_128_32_16;
cb_g<=g_256_64_16_8+g_2_1_d1;
cb_b<=b_512_8_2_1;
end
reg[17:0] cb_rg;
reg[17:0] cb_b_d1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
begin
cb_rg<=18'h3ffff;
cb_b_d1<=18'h3ffff;
end
else
begin
cb_rg<=cb_r+cb_g;
cb_b_d1<=cb_b;
end
reg[17:0] cb_rgb;
always@(posedge clk or negedge ngreset)
if(!ngreset)
cb_rgb<=18'h3ffff;
else if(cb_rg>cb_b_d1)
cb_rgb<=cb_rg-cb_b_d1;
else
cb_rgb<=cb_b_d1-cb_rg;
wire[7:0] cb_rgb_d1;
assign cb_rgb_d1=cb_rgb[17:10];
reg[7:0] cb_tmp;
always@(posedge clk or negedge ngreset)
if(!ngreset)
cb_tmp<=8'h0;
else if(cb_rg>cb_b_d1)
cb_tmp<=8'd128-cb_rgb_d1;
else
cb_tmp<=8'd128+cb_rgb_d1;
reg[7:0] y_tmp_d1;
always@(posedge clk or negedge ngreset)
if(!ngreset)
y_tmp_d1<=8'd0;
else
y_tmp_d1<=y_tmp;
assign Y=y_tmp_d1;
assign Cb=cb_tmp;
assign Cr=cr_tmp;
endmodule
3. tb_rgb_to_ycbcr.v `timescale 1ns/1ps
module tb_rgb_to_ycbcr();
reg clk,ngreset;
wire [7:0] R,G,B;
wire [7:0] Y,Cb,Cr;
initial
begin
clk=0;
ngreset=1;
#50 ngreset=0;
#100 ngreset=1;
end
always #5 clk=~clk;
reg[23:0] rgb_in[0:15];
initial begin
$readmemb("rgb_in.txt",rgb_in);
end
integer i;
always@(posedge clk or negedge ngreset)
if(!ngreset)
i<=0;
else if(i==15)
i<=0;
else
i<=i+1;
wire[23:0] data;
assign data=rgb_in[i];
assign R = data[23:16];
assign G = data[15:8 ];
assign B = data[7 :0 ];
rgb_to_ycbcr rgb_to_ycbcr_tmpt(.R(R),
.G(G),
.B(B),
.clk(clk),
.ngreset(ngreset),
.Y(Y),
.Cb(Cb),
.Cr(Cr));
initial
begin
$fsdbDumpfile("csc.fsdb");
$fsdbDumpvars(0,tb_rgb_to_ycbcr);
#100000 $finish;
end
//initial begin
// $dumpfile("ycbcr_out.dump");
// $dumplimit(409600);
// $dumpvars(0,rgb_to_ycbcr_tmpt);
// $dumpvars(0,rgb_to_ycbcr_tmpt.Y,rgb_to_ycbcr_tmpt.Cb,rgb_to_ycbcr_tmpt.Cr);
//end
endmodule
シミュレーション波形図1.Modelsimシミュレーション波形図
2.Nc-verilogシミュレーション波形図
まとめ
1.本コードは統合可能なコード方式で記述されているため、コードの長さが長く、例えば加算時に2つの数だけ加算し、シフト方式で乗算を実現し、後で乗算器を用いて改善することができる.
2.本コードは色度空間変換の任務を完全に実現し、総合的なコードであり、最後に出力されたYCBCR信号は入力されたRGB信号より6クロック遅延し、3つの出力信号は整列を実現する.
3.本コードの作成により、ファイルからデータを読み取り、ファイルに出力するプロセスを熟知しています.
4.シフトによる乗算の実現の考え方を熟知しており,以降のコード作成に啓発的である.