色度空间转换CSC(RGB转换YCBCR)的可综合verilog代码编写

转载请注明来源。

色度空间转换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.   本代码完整实现了色度空间转换的任务,并且是可综合的代码,最后输出的YCBCR信号比输入的RGB信号延迟了6个时钟,三个输出信号实现对齐。

3.   通过本代码的编写熟悉了从文件中读取数据和输出数据到文件的过程。

4.  熟悉了通过移位实现乘法的思想,对以后编写代码有启发意义。




你可能感兴趣的:(色度空间转换CSC(RGB转换YCBCR)的可综合verilog代码编写)