色度空間変換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
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.シフトによる乗算の実現の考え方を熟知しており,以降のコード作成に啓発的である.