csconvert.v 15.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*!
 * <b>Module:</b>csconvert
 * @file csconvert.v
 * @date 2015-06-14  
 * @author Andrey Filippov     
 *
 * @brief Color space convert: combine differnt color modes
 *
 * @copyright Copyright (c) 2015 Elphel, Inc.
 *
 * <b>License:</b>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * csconvert.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  csconvert.v is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
25 26 27 28 29 30
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
31
 * files and/or simulating the code, the copyright holders of this Program give
32 33
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
34
 * charge, and there is no dependence on any encrypted modules for simulating of
35 36 37
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
38
 */
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
`timescale 1ns/1ps

module  csconvert#(
        parameter CMPRS_COLOR18 =           0, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer
        parameter CMPRS_COLOR20 =           1, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer (not implemented)
        parameter CMPRS_MONO16 =            2, // JPEG 4:2:0 with 16x16 non-overlapping tiles, color components zeroed
        parameter CMPRS_JP4 =               3, // JP4 mode with 16x16 macroblocks
        parameter CMPRS_JP4DIFF =           4, // JP4DIFF mode TODO: see if correct
        parameter CMPRS_MONO8 =             7  // Regular JPEG monochrome with 8x8 macroblocks (not yet implemented)
)(
         input             xclk,
         input             frame_en,
         input      [ 2:0] converter_type,
                   
         input             ignore_color,   //zero Cb/Cr components
//         input             four_blocks, // use only 4 blocks for the output, not 6
//         input             jp4_dc_improved, // in JP4 mode, compare DC coefficients to the same color ones
         input             scale_diff,     // divide differences by 2 (to fit in 8-bit range)
         input             hdr,            // second green absolute, not difference
         input             limit_diff,   // 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream (==1)
         input      [ 9:0] m_cb,         // [9:0] scale for CB - default 0.564 (10'h90)
         input      [ 9:0] m_cr,         // [9:0] scale for CB - default 0.713 (10'hb6)
         input      [ 7:0] mb_din,       // input bayer data in scanline sequence, GR/BG sequence
         input      [ 1:0] bayer_phase,
63
         input             pre2_first_in, // marks the first input pixel (2 cycles ahead)
64 65 66 67 68 69 70 71 72 73 74 75 76
         
         output reg [ 8:0] signed_y,     //  - now signed char, -128(black) to +127 (white)
         output reg [ 8:0] signed_c,            // new, q is just signed char
         output reg [ 7:0] yaddrw,        // address for the external buffer memory to write 16x16x8bit Y data
         output reg        ywe,          // wrire enable of Y data
         output reg [ 7:0] caddrw,        // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
         output reg        cwe,          // write enable for CbCr data
         output reg        pre_first_out,
         
//         output reg        pre_color_enable,
//         output reg        ccv_out_start,     //TODO: adjust to minimal latency?
         output reg [ 7:0] n000, // not clear how they are used, make them just with latency1 from old
         output reg [ 7:0] n255);
77
    reg            pre_first_in;
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    // outputs to be multiplexed:
    wire   [7:0]   conv18_signed_y, conv20_signed_y, mono16_signed_y, jp4_signed_y;
    wire   [8:0]   jp4diff_signed_y, conv18_signed_c, conv20_signed_c;
    wire   [7:0]   conv18_yaddrw, conv20_yaddrw, mono16_yaddrw, jp4_yaddrw, jp4diff_yaddrw;
    wire   [6:0]   conv18_caddrw, conv20_caddrw;
    wire           conv18_ywe, conv18_cwe, conv20_ywe, conv20_cwe, mono16_ywe, jp4_ywe, jp4diff_ywe;
    wire           conv18_pre_first_out, conv20_pre_first_out, mono16_pre_first_out, jp4_pre_first_out, jp4diff_pre_first_out;

    wire   [7:0]   conv18_n000, conv20_n000, mono16_n000, jp4_n000, jp4diff_n000;
    wire   [7:0]   conv18_n255, conv20_n255, mono16_n255, jp4_n255, jp4diff_n255;
    
    reg    [ 7:0] en_converters;    
    reg           ignore_color_r;       //zero Cb/Cr components
    reg    [2:0]   converter_type_r;
//    reg            jp4_dc_improved_r;
//    reg            four_blocks_r;
    reg            scale_diff_r;
    reg            hdr_r;
//    reg    [1:0]   tile_margin_r;
    reg    [1:0]   bayer_phase_r;
//    reg    [3:0]   bayer_phase_onehot;
//    wire           limit_diff     = 1'b1;  // as in the prototype - just a constant 1
/*
    reg [5:0]  component_numsLS;  // component_num [0]
    reg [5:0]  component_numsMS;  // component_num [1]
    reg [5:0]  component_numsHS;  // component_num [2]
    reg [5:0]  component_colorsS; // use color quantization table (YCbCR, jp4diff)
    reg [5:0]  component_firstsS; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
*/
    always @ (posedge xclk) begin
108 109
        pre_first_in <= pre2_first_in;
        if (pre2_first_in) begin
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
            converter_type_r [2:0] <= converter_type[2:0];
            ignore_color_r         <= ignore_color;
//            jp4_dc_improved_r      <= jp4_dc_improved;
//            four_blocks_r          <= four_blocks;
            scale_diff_r           <= scale_diff;
            hdr_r                  <= hdr;
//            tile_margin_r[1:0]     <= tile_margin[1:0];
            bayer_phase_r[1:0]     <= bayer_phase[1:0];
//            bayer_phase_onehot[3:0]<={(bayer_phase[1:0]==2'h3)?1'b1:1'b0,
//                                      (bayer_phase[1:0]==2'h2)?1'b1:1'b0,
//                                      (bayer_phase[1:0]==2'h1)?1'b1:1'b0,
//                                      (bayer_phase[1:0]==2'h0)?1'b1:1'b0};
        end
    
        // generate one-hot converter enable  
125 126
        if      (!frame_en)      en_converters[CMPRS_COLOR18] <= 0;
        else if (pre2_first_in)  en_converters[CMPRS_COLOR18] <= converter_type == CMPRS_COLOR18;
127
        
128 129
        if       (!frame_en)     en_converters[CMPRS_COLOR20] <= 0;
        else  if (pre2_first_in) en_converters[CMPRS_COLOR20] <= converter_type == CMPRS_COLOR20;
130
        
131 132
        if      (!frame_en)      en_converters[CMPRS_MONO16] <=  0;
        else if (pre2_first_in)  en_converters[CMPRS_MONO16] <=  converter_type == CMPRS_MONO16;
133
        
134 135
        if      (!frame_en)      en_converters[CMPRS_JP4] <=     0;
        else if (pre2_first_in)  en_converters[CMPRS_JP4] <=     converter_type == CMPRS_JP4;
136
        
137 138
        if      (!frame_en)      en_converters[CMPRS_JP4DIFF] <= 0;
        else if (pre2_first_in)  en_converters[CMPRS_JP4DIFF] <= converter_type == CMPRS_JP4DIFF;
139
        
140 141
        if      (!frame_en)      en_converters[CMPRS_MONO8] <=   0;
        else if (pre2_first_in)  en_converters[CMPRS_MONO8] <=   converter_type == CMPRS_MONO8;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    end


 csconvert18a    i_csconvert18 (
                         .RST           (!en_converters[CMPRS_COLOR18]), // input
                         .CLK           (xclk),                // input
                         .mono          (ignore_color_r),      // input
                         .limit_diff    (limit_diff),          // input 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream
                         .m_cb          (m_cb[9:0]),           // input[9:0] scale for CB - default 0.564 (10'h90)
                         .m_cr          (m_cr[9:0]),           // input[9:0] scale for CB - default 0.713 (10'hb6)
                         .din           (mb_din[7:0]),         // input[7:0]
                         .pre_first_in  (pre_first_in),        // input
                         .signed_y      (conv18_signed_y[7:0]),// output[7:0]
                         .q             (conv18_signed_c[8:0]),// output[8:0] 
                         .yaddr         (conv18_yaddrw[7:0]),  // output[7:0] 
                         .ywe           (conv18_ywe),          // output
                         .caddr         (conv18_caddrw[6:0]),  // output[6:0] 
                         .cwe           (conv18_cwe),          // output
                         .pre_first_out (conv18_pre_first_out),// output
                         .bayer_phase   (bayer_phase_r[1:0]),  // input[1:0]
                         .n000          (conv18_n000[7:0]),    // output[7:0] 
                         .n255          (conv18_n255[7:0]));   // output[7:0] 

 csconvert_mono i_csconvert_mono (
                         .en            (en_converters[CMPRS_MONO16]),
                         .clk           (xclk),
                         .din           (mb_din[7:0]),
                         .pre_first_in  (pre_first_in),
                         .y_out         (mono16_signed_y[7:0]),
                         .yaddr         (mono16_yaddrw[7:0]),
                         .ywe           (mono16_ywe),
                         .pre_first_out(mono16_pre_first_out));
 csconvert_jp4 i_csconvert_jp4 (
                         .en            (en_converters[CMPRS_JP4]),
                         .clk           (xclk),
                         .din           (mb_din[7:0]),
                         .pre_first_in  (pre_first_in),
                         .y_out         (jp4_signed_y[7:0]),
                         .yaddr         (jp4_yaddrw[7:0]),
                         .ywe           (jp4_ywe),
                         .pre_first_out (jp4_pre_first_out));

 csconvert_jp4diff i_csconvert_jp4diff (
                         .en            (en_converters[CMPRS_JP4DIFF]),
                         .clk           (xclk),
                         .scale_diff    (scale_diff_r),
                         .hdr           (hdr_r),
                         .din           (mb_din[7:0]),
                         .pre_first_in  (pre_first_in),
                         .y_out         (jp4diff_signed_y[8:0]),
                         .yaddr         (jp4diff_yaddrw[7:0]),
                         .ywe           (jp4diff_ywe),
                         .pre_first_out (jp4diff_pre_first_out),
                         .bayer_phase   (bayer_phase_r[1:0]));


    //TODO:  temporary plugs, until module for 20x20 is created
    // will be wrong, of course
    assign conv20_signed_y[7:0]=     conv18_signed_y[7:0];
    assign conv20_yaddrw[7:0]=   conv18_yaddrw[7:0];
    assign conv20_ywe=           conv18_ywe;
    assign conv20_signed_c[8:0]=     conv18_signed_c[8:0];
    assign conv20_caddrw[6:0]=   conv18_caddrw[6:0];
    assign conv20_cwe=           conv18_cwe;
    assign conv20_pre_first_out= conv18_pre_first_out;
    // TODO: temporary assign N000 and N255 for other (not csconvert18) modes until they are implemented in those modules

    assign conv20_n000=   conv18_n000;
    assign mono16_n000=   conv18_n000;
    assign jp4_n000=      conv18_n000;
    assign jp4diff_n000=  conv18_n000;
    assign conv20_n255=   conv18_n255;
    assign mono16_n255=   conv18_n255;
    assign jp4_n255=      conv18_n255;
    assign jp4diff_n255=  conv18_n255;

// multiplex outputs
 // average for each block should be calculated before the data goes to output output
  always @ (posedge xclk) case (converter_type_r[2:0])
    CMPRS_COLOR18:begin //color 18
          pre_first_out <= conv18_pre_first_out;
          signed_y[8:0]        <= {conv18_signed_y[7],conv18_signed_y[7:0]};
          ywe              <= conv18_ywe;
          yaddrw[7:0]      <= {conv18_yaddrw[7],conv18_yaddrw[3],conv18_yaddrw[6:4],conv18_yaddrw[2:0]};
          signed_c[8:0]        <= {conv18_signed_c[8:0]};
          cwe              <= conv18_cwe;
          caddrw[7:0]      <= {1'b0,conv18_caddrw[6:0]};
          n000             <= conv18_n000;
          n255             <= conv18_n255;
//          pre_color_enable <= 1'b1;
//          ccv_out_start    <= (conv18_yaddrw[7:0]==8'hc5); //TODO: adjust to minimal latency?
         end
    CMPRS_COLOR20:begin //color 20
          pre_first_out <= conv20_pre_first_out;
          signed_y[8:0]        <= {conv20_signed_y[7],conv20_signed_y[7:0]};
          ywe              <= conv20_ywe;
          yaddrw[7:0]      <= {conv20_yaddrw[7],conv20_yaddrw[3],conv20_yaddrw[6:4],conv20_yaddrw[2:0]};
          signed_c[8:0]        <= {conv20_signed_c[8:0]};
          cwe              <= conv20_cwe;
          caddrw[7:0]      <= {1'b0,conv20_caddrw[6:0]};
          n000             <= conv20_n000;
          n255             <= conv20_n255;
          
 //         pre_color_enable <= 1'b1;
 //         ccv_out_start    <= (conv20_yaddrw[7:0]==8'hc5); //TODO: adjust to minimal latency?
         end
    CMPRS_MONO16:begin //mono
          pre_first_out <= mono16_pre_first_out;
          signed_y[8:0]        <= {mono16_signed_y[7],mono16_signed_y[7:0]};
          ywe              <= mono16_ywe;
          yaddrw[7:0]      <= {mono16_yaddrw[7],mono16_yaddrw[3],mono16_yaddrw[6:4],mono16_yaddrw[2:0]};
          signed_c[8:0]        <= 9'h0;
          cwe              <= 1'b0;
          caddrw[7:0]      <= 8'h0;
          n000             <= mono16_n000;
          n255             <= mono16_n255;
          
//          pre_color_enable <= 1'b0;
//          ccv_out_start    <=  accYdone[0];
         end
    CMPRS_JP4:begin // jp4
          pre_first_out <= jp4_pre_first_out;
          signed_y[8:0]        <= {jp4_signed_y[7],jp4_signed_y[7:0]};
          ywe              <= jp4_ywe;
          yaddrw[7:0]      <= {jp4_yaddrw[7],jp4_yaddrw[3],jp4_yaddrw[6:4],jp4_yaddrw[2:0]};
          signed_c[8:0]        <= 9'h0;
          cwe              <= 1'b0;
          caddrw[7:0]      <= 8'h0;
          n000             <= jp4_n000;
          n255             <= jp4_n255;
          
//          pre_color_enable <= 1'b0;
//          ccv_out_start    <=  accYdone[0];
         end
    CMPRS_JP4DIFF:begin //jp4diff
          pre_first_out <= jp4diff_pre_first_out;
          signed_y[8:0]        <= {jp4diff_signed_y[8:0]};
          ywe              <= jp4diff_ywe;
          yaddrw[7:0]      <= {jp4diff_yaddrw[7],jp4diff_yaddrw[3],jp4diff_yaddrw[6:4],jp4diff_yaddrw[2:0]};
          signed_c[8:0]        <= 9'h0;
          cwe              <= 1'b0;
          caddrw[7:0]      <= 8'h0;
          n000             <= jp4diff_n000;
          n255             <= jp4diff_n255;
          
//          pre_color_enable <= 1'b0;
//          ccv_out_start    <=  accYdone[0];
         end
Andrey Filippov's avatar
Andrey Filippov committed
290 291 292 293 294 295 296 297 298 299 300 301
    default:begin //color 18 (or try 'X'
          pre_first_out    <= 'bx; // conv18_pre_first_out;
          signed_y[8:0]    <= 'bx; // {conv18_signed_y[7],conv18_signed_y[7:0]};
          ywe              <= 'bx; //conv18_ywe;
          yaddrw[7:0]      <= 'bx; //{conv18_yaddrw[7],conv18_yaddrw[3],conv18_yaddrw[6:4],conv18_yaddrw[2:0]};
          signed_c[8:0]    <= 'bx; //{conv18_signed_c[8:0]};
          cwe              <= 'bx; //conv18_cwe;
          caddrw[7:0]      <= 'bx; //{1'b0,conv18_caddrw[6:0]};
          n000             <= 'bx; //conv18_n000;
          n255             <= 'bx; //conv18_n255;
         end
         
302 303 304 305 306 307 308 309
  endcase

    
    
    

endmodule