Loading compressor_jp/jp_channel.v +82 −13 Original line number Original line Diff line number Diff line Loading @@ -125,14 +125,14 @@ module jp_channel#( wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) wire [ 8:0] yc_avr; // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff! wire [ 8:0] yc_avr; // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff! wire yc_nodc_dv; // out data valid (will go high for at least 64 cycles) wire yc_nodc_dv; // out data valid (will go high for at least 64 cycles) wire yc_nodc_ds; // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block wire dct_start; // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block wire [ 2:0] yc_nodc_tn; // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start) wire [ 2:0] color_tn; // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start) wire yc_nodc_first; // sending first_r MCU (valid @ ds) wire color_first; // sending first_r MCU (valid @ ds) wire yc_nodc_last; // sending last_r MCU (valid @ ds) wire color_last; // sending last_r MCU (valid @ ds) // below signals valid at ds ( 1 later than tn, first_r, last_r) // below signals valid at ds ( 1 later than tn, first_r, last_r) wire [2:0] yc_nodc_component_num; //[2:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) 4 - don't use wire [2:0] yc_nodc_component_num; //[2:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) 4 - don't use wire yc_nodc_component_color; // use color quantization table (YCbCR, jp4diff) wire yc_nodc_component_color; // use color quantization table (YCbCR, jp4diff) wire yc_nodc_component_first; // first_r this component in a frame (DC absolute, otherwise - difference to previous) wire color_first; // first_r this component in a frame (DC absolute, otherwise - difference to previous) wire yc_nodc_component_lastinmb; // last_r component in a macroblock; wire yc_nodc_component_lastinmb; // last_r component in a macroblock; Loading Loading @@ -293,13 +293,13 @@ module jp_channel#( .do (yc_nodc), // output[9:0] .do (yc_nodc), // output[9:0] .avr (yc_avr), // output[8:0] .avr (yc_avr), // output[8:0] .dv (yc_nodc_dv), // output .dv (yc_nodc_dv), // output .ds (yc_nodc_ds), // output .ds (dct_start), // output .tn (yc_nodc_tn), // output[2:0] .tn (color_tn), // output[2:0] .first (yc_nodc_first), // output reg .first (color_first), // output reg .last (yc_nodc_last), // output reg .last (color_last), // output reg .component_num (yc_nodc_component_num), // output[2:0] .component_num (yc_nodc_component_num), // output[2:0] .component_color (yc_nodc_component_color), // output .component_color (yc_nodc_component_color), // output .component_first (yc_nodc_component_first), // output .component_first (color_first), // output .component_lastinmb (yc_nodc_component_lastinmb) // output reg .component_lastinmb (yc_nodc_component_lastinmb) // output reg ); ); // wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) // wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) Loading @@ -309,18 +309,87 @@ module jp_channel#( wire dct_dv; wire dct_dv; wire [12:0] dct_out; wire [12:0] dct_out; //propagation of first block through compressor pipeline wire first_block_color=(color_tn[2:0]==3'h0) && color_first; // while color conversion, reg first_block_color_after; // after color conversion, reg first_block_dct; // after DCT wire first_block_quant; // after quantizer always @ (posedge clk) begin if (dct_start) first_block_color_after <= first_block_color; if (dct_last_in) first_block_dct <= first_block_color_after; end xdct393 xdct393_i ( xdct393 xdct393_i ( .clk (xclk), // input .clk (xclk), // input .en (frame_en), // input if zero will reset transpose memory page numbers .en (frame_en), // input if zero will reset transpose memory page numbers .start (yc_nodc_ds), // input single-cycle start pulse that goes with the first pixel data. Other 63 should follow .start (dct_start), // input single-cycle start pulse that goes with the first pixel data. Other 63 should follow .xin (yc_nodc), // input[9:0] .xin (yc_nodc), // input[9:0] .last_in (dct_last_in), // output reg output high during input of the last of 64 pixels in a 8x8 block // .last_in (dct_last_in), // output reg output high during input of the last of 64 pixels in a 8x8 block // .pre_first_out (dct_pre_first_out), // outpu 1 cycle ahead of the first output in a 64 block .pre_first_out (dct_pre_first_out), // outpu 1 cycle ahead of the first output in a 64 block .dv (dct_dv), // output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?) .dv (dct_dv), // output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?) .d_out (dct_out) // output[12:0] .d_out (dct_out) // output[12:0] ); ); reg quant_start; wire quant_start; always @ (posedge xclk) quant_start <= dct_pre_first_out; dly_16 #(.WIDTH(1)) i_quant_start (.clk(xclk),.rst(1'b0), .dly(0), .din(dct_pre_first_out), .dout(quant_start)); // dly=0+1 // TODO: Change interface wire twqe; wire twce; wire [8:0] ta; wire [15:0] tdi; reg [ 2:0] cmprs_qpage_this; wire first_block_quant; wire [12:0] quant_do; wire quant_ds; wire [15:0] quant_dc_tdo;// MSB aligned coefficient for the DC component (used in focus module) wire [ 2:0] coring_num; reg dcc_en; wire dccout; wire [ 2:0] hfc_sel; wire dccvld; always @ (posedge clk) begin if (!dccout) dcc_en <=1'b0; else if (dct_start && color_first && (color_tn[2:0]==3'b001)) dcc_en <=1'b1; // 3'b001 - closer to the first "start" in quantizator end quantizer393 quantizer393_i ( .clk (xclk), // input .en (frame_en), // input .sclk (mclk), // input system clock, twqe, twce, ta,tdi - valid @posedge (ra, tdi - 2 cycles ahead (was negedge) .twqe (twqe), // input enable write to a quantization table .twce (twce), // input enable write to a coring table .ta (ta), // input[8:0] table address .tdi (tdi), // input[15:0] data in (8 LSBs - quantization data - obsolete?) .ctypei (yc_nodc_component_color),// input component type input (Y/C) .dci (yc_avr), // input[8:0] - average value in a block - subtracted before DCT. now normal signed number .first_stb (first_block_color), // input - this is first stb pulse in a frame .stb (dct_start), // input - strobe that writes ctypei, dci .tsi (cmprs_qpage_this[2:0]), // input[2:0] - table (quality) select [2:0] .pre_start (dct_pre_first_out), // input - marks first input pixel (one before) .first_in (first_block_dct), // input - first block in (valid @ start) .first_out (first_block_quant), // output reg - valid @ ds .di (dct_out[12:0]), // input[12:0] - pixel data in (signed) .do (quant_do[12:0]), // output[12:0] - pixel data out (AC is only 9 bits long?) - changed to 10 .dv (), // output reg - data out valid .ds (quant_ds), // output reg - data out strobe (one ahead of the start of dv) .dc_tdo (quant_dc_tdo[15:0]), // output[15:0] reg - MSB aligned coefficient for the DC component (used in focus module) .dcc_en (dcc_en), // input - enable dcc (sync to beginning of a new frame) .hfc_sel (hfc_sel), // input[2:0] - hight frequency components select [2:0] (includes components with both numbers >=hfc_sel .color_first (color_first), // input - first MCU in a frame .coring_num (coring_num), // input[2:0] - coring table pair number (0..7) .dcc_vld (dccvld), // output reg - single cycle when dcc_data is valid .dcc_data (), // output[15:0] - dc component data out (for reading by software) .n000 (n000), // input[7:0] - number of zero pixels (255 if 256) - to be multiplexed with dcc .n255 (n255) // input[7:0] - number of 0xff pixels (255 if 256) - to be multiplexed with dcc ); /* /* xdct i_xdct ( .clk(clk), // top level module xdct i_xdct ( .clk(clk), // top level module Loading compressor_jp/quantizer393.v 0 → 100644 +363 −0 Original line number Original line Diff line number Diff line /* ** -----------------------------------------------------------------------------** ** quantizator353.v ** ** Quantizer module for JPEG compressor ** ** Copyright (C) 2002-2015 Elphel, Inc ** ** -----------------------------------------------------------------------------** ** quantizer393.v is free software - hardware description language (HDL) code. ** ** This program 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. ** ** This program 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/>. ** -----------------------------------------------------------------------------** ** */ `timescale 1ns/1ps // will add extracted DC (8 bits) to data from DCT here that will make data 12 bits (signed) long. // It will be possible to make a sequintial multiplier for DC - but I'll skip this now. module quantizer393( input clk, // pixel clock, posedge input en, // enable (0 resets counter) input sclk, // system clock, twqe, twce, ta,tdi - valid @posedge (ra, tdi - 2 cycles ahead (was negedge) input twqe, // enable write to a quantization table input twce, // enable write to a coring table input [ 8:0] ta, // [8:0] table address input [15:0] tdi, // [15:0] table data in (8 LSBs - quantization data) input ctypei, // component type input (Y/C) input [ 8:0] dci, // [7:0] - average value in a block - subtracted before DCT. now normal signed number input first_stb, //this is first stb pulse in a frame input stb, // strobe that writes ctypei, dci input [ 2:0] tsi, // table (quality) select [2:0] input pre_start,// marks first input pixel (one before) input first_in, // first block in (valid @ start) output reg first_out, // valid @ ds input [12:0] di, // [11:0] pixel data in (signed) output [12:0] do, // [11:0] pixel data out (AC is only 9 bits long?) - changed to 10 output reg dv, // data out valid output reg ds, // data out strobe (one ahead of the start of dv) output reg [15:0] dc_tdo, //[15:0], MSB aligned coefficient for the DC component (used in focus module) input dcc_en, // enable dcc (sync to beginning of a new frame) input [ 2:0] hfc_sel, // hight frequency components select [2:0] (includes components with both numbers >=hfc_sel // hfc_sel == 3'h7 - now high frequency output - just 3 words - brightness and 2 color diffs input color_first, // first MCU in a frame input [ 2:0] coring_num, // coring table pair number (0..7) output reg dcc_vld, // single cycle when dcc_data is valid output [15:0] dcc_data, // [15:0] dc component data out (for reading by software) input [ 7:0] n000, // input [7:0] number of zero pixels (255 if 256) - to be multiplexed with dcc input [ 7:0] n255); // input [7:0] number of 0xff pixels (255 if 256) - to be multiplexed with dcc wire [3:0] tdco; // coring table output reg [3:0] tbac; // coring memory table number (LSB - color) reg coring_range; // input <16, use coring LUT wire [15:0] tdo; reg [ 9:0] tba; // table output (use) address wire [15:0] zigzag_q; reg wpage; reg rpage; wire [ 5:0] zwa; reg [ 5:0] zra; reg [12:0] qdo; reg [12:0] qdo0; reg zwe; reg [12:0] d1; reg [12:0] d2,d3; // registered data in, converted to sign+ absolute value wire [27:0] qmul; wire start_a; reg [15:0] tdor; reg [20:0] qmulr; // added 7 bits to total8 fractional for biasing/zero bin wire start_out; wire start_z; reg [ 8:0] dc1; // registered DC average - with restored sign // for fifo for ctype, dc wire ctype; wire [ 8:0] dc; wire next_dv; reg [ 5:0] start; wire dcc_stb; reg dcc_run; reg dcc_first; reg dcc_Y; reg [ 1:0] ctype_prev; reg [12:0] dcc_acc; reg [12:0] hfc_acc; wire hfc_en; reg hfc_copy; // copy hfc_acc to dcc_acc wire [10:0] d2_dct; // 11 bits enough, convetred to positive (before - 0 was in the middle - pixel value 128) - dcc only reg sel_satnum; // select saturation numbers - dcc only reg twqe_d; //twqe delayed (write MSW) reg twce_d; //twce delayed (write MSW) reg [15:0] pre_dc_tdo; wire copy_dc_tdo; reg first_interm; // valid @ ds wire [ 2:0] ts; wire [ 2:0] coring_sel; reg [ 2:0] block_mem_ra; reg [ 2:0] block_mem_wa; reg [ 2:0] block_mem_wa_save; reg [15:0] block_mem[0:7]; wire [15:0] block_mem_o=block_mem[block_mem_ra[2:0]]; assign dc[8:0] = block_mem_o[8:0]; assign ctype = block_mem_o[9]; assign ts[2:0] = block_mem_o[12:10]; assign coring_sel[2:0] = block_mem_o[15:13]; assign start_a = start[5]; assign start_z = start[4]; assign dcc_stb = start[2]; always @ (posedge clk) begin if (stb) block_mem[block_mem_wa[2:0]] <= {coring_num[2:0],tsi[2:0], ctypei, dci[8:0]}; if (!en) block_mem_wa[2:0] <= 3'h0; else if (stb) block_mem_wa[2:0] <= block_mem_wa[2:0] +1; if (stb && first_stb) block_mem_wa_save[2:0] <= block_mem_wa[2:0]; if (!en) block_mem_ra[2:0] <= 3'h0; else if (pre_start) block_mem_ra[2:0] <= first_in?block_mem_wa_save[2:0]:(block_mem_ra[2:0] +1); end assign d2_dct[10:0]={!d2[11] ^ ctype_prev[0], d2[9:0]}; assign dcc_data[15:0]=sel_satnum? {n255[7:0],n000[7:0]}: {dcc_first || (!dcc_Y && dcc_acc[12]) ,(!dcc_Y && dcc_acc[12]), (!dcc_Y && dcc_acc[12]), dcc_acc[12:0]}; assign do[12:0]=zigzag_q[12:0]; assign qmul[27:0]=tdor[15:0]*d3[11:0]; assign start_out = zwe && (zwa[5:0]== 6'h3f); //adjust? assign copy_dc_tdo = zwe && (zwa[5:0]== 6'h37); // not critical assign next_dv=en && (ds || (dv && (zra[5:0]!=6'h00))); always @ (posedge clk) begin d1[12:0] <= di[12:0]; //inv_sign dc1[8:0] <= start[0]?dc[8:0]:9'b0; // sync to d1[8:0]ctype valid at start, not later d2[12:0] <= {dc1[8],dc1[8:0],3'b0} + d1[12:0]; d3[12] <= d2[12]; d3[11:0] <= d2[12]? -d2[11:0]:d2[11:0]; if (start[0] || !en) tba[9:6] <= {ts[2:0],ctype}; /// TODO - make sure ctype switches at needed time (compensate if needed) ***************************************** if (start[3] || !en) tbac[3:0] <= {coring_sel[2:0],ctype}; // table number to use if (start[0]) tba[5:0] <= 6'b0; else if (tba[5:0]!=6'h3f) tba[5:0] <= tba[5:0]+1; tdor[15:0] <= tdo[15:0]; // registered table data out if (start[3]) pre_dc_tdo[15:0] <= tdor[15:0]; //16-bit q. tables) if (copy_dc_tdo) dc_tdo[15:0] <= pre_dc_tdo[15:0]; qmulr[19:0] <= qmul[27:8]; // absolute value qmulr[20] <= d3[12]; // sign qdo0[12] <= qmulr[20]; // sign // tdco[3:0] - same timing as qdo0; // use lookup table from 8 bits of absolute value (4.4 - 4 fractional) to calculate 4 bit coring output that would replace output // if input is less thahn 16. For larger values the true rounding will be used. // Absolute values here have quantization coefficients already applied, so we can use the same coring table for all DCT coefficients. // there are be 16 tables - 8 Y/C pairs to switch qdo0[11:0] <= qmulr[19:8] + qmulr[7]; // true rounding of the absolute value coring_range<= !(|qmulr[19:12]) && !(&qmulr[11:7]) ; // valid with qdo0 qdo[11:0] <= coring_range? (qdo0[12]?-{8'h0,tdco[3:0]}:{8'h0,tdco[3:0]}):(qdo0[12]?-qdo0[11:0]:qdo0[11:0]); qdo[12] <= qdo0[12] && (!coring_range || (tdco[3:0]!=4'h0)); if (start_out) rpage <= wpage; if (start_out) zra[5:0] <= 6'b0; else if (zra[5:0]!=6'h3f) zra[5:0] <= zra[5:0]+1; // conserving energy ds <= start_out; dv <= next_dv; if (start_a) first_interm <= first_in; if (start_out) first_out <=first_interm; // zwe??? zwe <= en && (start_a || (zwe && (zwa[5:0]!=6'h3f))); if (!en) wpage <= 1'b0; else if (start_a) wpage <= ~wpage; end always @ (posedge clk) begin sel_satnum <= dcc_run && (start[0]? (ctype_prev[1:0]==2'b10): sel_satnum); hfc_copy <= dcc_run && (hfc_sel[2:0]!=3'h7) && (tba[5:0]==6'h1f) && ctype_prev[0] && ctype_prev[1]; start[5:0] <= {start[4:0], pre_start}; // needed? if (!dcc_en) dcc_run <= 1'b0; else if (start[0]) dcc_run <= 1'b1; if (!dcc_en) ctype_prev[1:0] <= 2'b11; else if (start[0]) ctype_prev[1:0] <= {ctype_prev[0],ctype && dcc_run}; if (dcc_stb || hfc_copy) dcc_acc[12:0] <= hfc_copy? hfc_acc[12:0]: {(d2_dct[10]&&ctype_prev[0]),(d2_dct[10]&&ctype_prev[0]),d2_dct[10:0]}+((ctype_prev[0] || ctype_prev[1])?13'h0:dcc_acc[12:0]); if (!dcc_run || hfc_copy) hfc_acc <=13'b0; else if (hfc_en) hfc_acc <= hfc_acc + {2'b0, d3[10:0]}; if (dcc_stb) dcc_first <= color_first && dcc_run && dcc_stb && ctype && !ctype_prev[0]; if (dcc_stb) dcc_Y <= dcc_run && dcc_stb && ctype && !ctype_prev[0]; dcc_vld <= (dcc_run && dcc_stb && (ctype || ctype_prev[0] || sel_satnum)) || hfc_copy; end always @ (posedge sclk) begin twqe_d <= twqe; twce_d <= twce; end // SRL16 i_hfc_en (.Q(hfc_en), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(clk), // .D(((tba[2:0]>hfc_sel[2:0]) || (tba[5:3]>hfc_sel[2:0])) && dcc_run && !ctype_prev[0])); // dly=1+1 dly_16 #(.WIDTH(1)) i_hfc_en ( .clk(clk), .rst(1'b0), .dly(1), .din(((tba[2:0]>hfc_sel[2:0]) || (tba[5:3]>hfc_sel[2:0])) && dcc_run && !ctype_prev[0]), .dout(hfc_en)); // dly=1+1 zigzag393 i_zigzag( .clk(clk), .start(start_z), .q(zwa[5:0])); // All memories below are non-registered, see if they can be made registered ram18_var_w_var_r #( .REGISTERS (0), .LOG2WIDTH_WR (4), .LOG2WIDTH_RD (4), .DUMMY (0) ) i_quant_table ( .rclk (clk), // input .raddr ({tba[9:6],tba[2:0],tba[5:3]}), // input[8:0] .ren (1'b1), // input .regen (1'b0), // input .data_out (tdo[15:0]), // output[15:0] .wclk (sclk), // input .waddr ({ta[8:0],twqe_d}), // input[8:0] .we (twqe || twqe_d), // input .web (4'hf), // input[3:0] .data_in (tdi[15:0]) // input[15:0] ); ram18_var_w_var_r #( .REGISTERS (0), .LOG2WIDTH_WR (4), .LOG2WIDTH_RD (2), .DUMMY (0) ) i_coring_table ( .rclk (clk), // input .raddr ({tbac[3:0],qmulr[11:4]}), // input[10:0] .ren (1'b1), // input .regen (1'b0), // input .data_out (tdco[3:0]), // output[3:0] .wclk (sclk), // input .waddr ({ta[8:0],twce_d}), // input[9:0] .we (twce || twce_d), // input .web (4'hf), // input[3:0] .data_in (tdi[15:0]) // input[15:0] ); ram18_var_w_var_r #( .REGISTERS (0), .LOG2WIDTH_WR (4), .LOG2WIDTH_RD (4), .DUMMY (0) ) i_zigzagbuf ( .rclk (clk), // input .raddr ({3'b0,rpage,zra[5:0]}), // input[8:0] .ren (next_dv), // input .regen (1'b0), // input .data_out (zigzag_q[15:0]), // output[31:0] .wclk (clk), // input .waddr ({3'b0,wpage,zwa[5:0]}), // input[8:0] .we (zwe), // input .web (4'hf), // input[3:0] .data_in ({3'b0,qdo[12:0]}) // input[31:0] ); endmodule module zigzag393 ( input clk, // system clock, posedge input start, output reg [5:0] q); reg [5:0] a; wire [ 4:0] rom_a; reg [ 5:0] rom_q; assign rom_a[4:0]=a[5]?(~a[4:0]):a[4:0]; always @ (posedge clk) begin if (start) a[5:0] <= 6'b0; else if (a[5:0]!=6'h3f) a[5:0] <= a[5:0]+1; end // ROM (combinatorial) always @(rom_a) case (rom_a) 5'h00: rom_q <= 6'h00; 5'h01: rom_q <= 6'h02; 5'h02: rom_q <= 6'h03; 5'h03: rom_q <= 6'h09; 5'h04: rom_q <= 6'h0a; 5'h05: rom_q <= 6'h14; 5'h06: rom_q <= 6'h15; 5'h07: rom_q <= 6'h23; 5'h08: rom_q <= 6'h01; 5'h09: rom_q <= 6'h04; 5'h10: rom_q <= 6'h08; 5'h11: rom_q <= 6'h0b; 5'h12: rom_q <= 6'h13; 5'h13: rom_q <= 6'h16; 5'h14: rom_q <= 6'h22; 5'h15: rom_q <= 6'h24; 5'h16: rom_q <= 6'h05; 5'h17: rom_q <= 6'h07; 5'h18: rom_q <= 6'h0c; 5'h19: rom_q <= 6'h12; 5'h20: rom_q <= 6'h17; 5'h21: rom_q <= 6'h21; 5'h22: rom_q <= 6'h25; 5'h23: rom_q <= 6'h30; 5'h24: rom_q <= 6'h06; 5'h25: rom_q <= 6'h0d; 5'h26: rom_q <= 6'h11; 5'h27: rom_q <= 6'h18; 5'h28: rom_q <= 6'h20; 5'h29: rom_q <= 6'h26; 5'h30: rom_q <= 6'h2f; 5'h31: rom_q <= 6'h31; endcase // add symmetrical part always @ (posedge clk) q[5:0] <= a[5]? (~rom_q[5:0]):rom_q[5:0]; endmodule py393/.settings/org.eclipse.core.resources.prefs +1 −0 Original line number Original line Diff line number Diff line eclipse.preferences.version=1 eclipse.preferences.version=1 encoding/convert_zigzag_rom.py=utf-8 encoding/exp_gpio.py=utf-8 encoding/exp_gpio.py=utf-8 encoding/import_verilog_parameters.py=utf-8 encoding/import_verilog_parameters.py=utf-8 encoding/mon_gpio.py=utf-8 encoding/mon_gpio.py=utf-8 Loading Loading
compressor_jp/jp_channel.v +82 −13 Original line number Original line Diff line number Diff line Loading @@ -125,14 +125,14 @@ module jp_channel#( wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) wire [ 8:0] yc_avr; // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff! wire [ 8:0] yc_avr; // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff! wire yc_nodc_dv; // out data valid (will go high for at least 64 cycles) wire yc_nodc_dv; // out data valid (will go high for at least 64 cycles) wire yc_nodc_ds; // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block wire dct_start; // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block wire [ 2:0] yc_nodc_tn; // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start) wire [ 2:0] color_tn; // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start) wire yc_nodc_first; // sending first_r MCU (valid @ ds) wire color_first; // sending first_r MCU (valid @ ds) wire yc_nodc_last; // sending last_r MCU (valid @ ds) wire color_last; // sending last_r MCU (valid @ ds) // below signals valid at ds ( 1 later than tn, first_r, last_r) // below signals valid at ds ( 1 later than tn, first_r, last_r) wire [2:0] yc_nodc_component_num; //[2:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) 4 - don't use wire [2:0] yc_nodc_component_num; //[2:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) 4 - don't use wire yc_nodc_component_color; // use color quantization table (YCbCR, jp4diff) wire yc_nodc_component_color; // use color quantization table (YCbCR, jp4diff) wire yc_nodc_component_first; // first_r this component in a frame (DC absolute, otherwise - difference to previous) wire color_first; // first_r this component in a frame (DC absolute, otherwise - difference to previous) wire yc_nodc_component_lastinmb; // last_r component in a macroblock; wire yc_nodc_component_lastinmb; // last_r component in a macroblock; Loading Loading @@ -293,13 +293,13 @@ module jp_channel#( .do (yc_nodc), // output[9:0] .do (yc_nodc), // output[9:0] .avr (yc_avr), // output[8:0] .avr (yc_avr), // output[8:0] .dv (yc_nodc_dv), // output .dv (yc_nodc_dv), // output .ds (yc_nodc_ds), // output .ds (dct_start), // output .tn (yc_nodc_tn), // output[2:0] .tn (color_tn), // output[2:0] .first (yc_nodc_first), // output reg .first (color_first), // output reg .last (yc_nodc_last), // output reg .last (color_last), // output reg .component_num (yc_nodc_component_num), // output[2:0] .component_num (yc_nodc_component_num), // output[2:0] .component_color (yc_nodc_component_color), // output .component_color (yc_nodc_component_color), // output .component_first (yc_nodc_component_first), // output .component_first (color_first), // output .component_lastinmb (yc_nodc_component_lastinmb) // output reg .component_lastinmb (yc_nodc_component_lastinmb) // output reg ); ); // wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) // wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) Loading @@ -309,18 +309,87 @@ module jp_channel#( wire dct_dv; wire dct_dv; wire [12:0] dct_out; wire [12:0] dct_out; //propagation of first block through compressor pipeline wire first_block_color=(color_tn[2:0]==3'h0) && color_first; // while color conversion, reg first_block_color_after; // after color conversion, reg first_block_dct; // after DCT wire first_block_quant; // after quantizer always @ (posedge clk) begin if (dct_start) first_block_color_after <= first_block_color; if (dct_last_in) first_block_dct <= first_block_color_after; end xdct393 xdct393_i ( xdct393 xdct393_i ( .clk (xclk), // input .clk (xclk), // input .en (frame_en), // input if zero will reset transpose memory page numbers .en (frame_en), // input if zero will reset transpose memory page numbers .start (yc_nodc_ds), // input single-cycle start pulse that goes with the first pixel data. Other 63 should follow .start (dct_start), // input single-cycle start pulse that goes with the first pixel data. Other 63 should follow .xin (yc_nodc), // input[9:0] .xin (yc_nodc), // input[9:0] .last_in (dct_last_in), // output reg output high during input of the last of 64 pixels in a 8x8 block // .last_in (dct_last_in), // output reg output high during input of the last of 64 pixels in a 8x8 block // .pre_first_out (dct_pre_first_out), // outpu 1 cycle ahead of the first output in a 64 block .pre_first_out (dct_pre_first_out), // outpu 1 cycle ahead of the first output in a 64 block .dv (dct_dv), // output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?) .dv (dct_dv), // output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?) .d_out (dct_out) // output[12:0] .d_out (dct_out) // output[12:0] ); ); reg quant_start; wire quant_start; always @ (posedge xclk) quant_start <= dct_pre_first_out; dly_16 #(.WIDTH(1)) i_quant_start (.clk(xclk),.rst(1'b0), .dly(0), .din(dct_pre_first_out), .dout(quant_start)); // dly=0+1 // TODO: Change interface wire twqe; wire twce; wire [8:0] ta; wire [15:0] tdi; reg [ 2:0] cmprs_qpage_this; wire first_block_quant; wire [12:0] quant_do; wire quant_ds; wire [15:0] quant_dc_tdo;// MSB aligned coefficient for the DC component (used in focus module) wire [ 2:0] coring_num; reg dcc_en; wire dccout; wire [ 2:0] hfc_sel; wire dccvld; always @ (posedge clk) begin if (!dccout) dcc_en <=1'b0; else if (dct_start && color_first && (color_tn[2:0]==3'b001)) dcc_en <=1'b1; // 3'b001 - closer to the first "start" in quantizator end quantizer393 quantizer393_i ( .clk (xclk), // input .en (frame_en), // input .sclk (mclk), // input system clock, twqe, twce, ta,tdi - valid @posedge (ra, tdi - 2 cycles ahead (was negedge) .twqe (twqe), // input enable write to a quantization table .twce (twce), // input enable write to a coring table .ta (ta), // input[8:0] table address .tdi (tdi), // input[15:0] data in (8 LSBs - quantization data - obsolete?) .ctypei (yc_nodc_component_color),// input component type input (Y/C) .dci (yc_avr), // input[8:0] - average value in a block - subtracted before DCT. now normal signed number .first_stb (first_block_color), // input - this is first stb pulse in a frame .stb (dct_start), // input - strobe that writes ctypei, dci .tsi (cmprs_qpage_this[2:0]), // input[2:0] - table (quality) select [2:0] .pre_start (dct_pre_first_out), // input - marks first input pixel (one before) .first_in (first_block_dct), // input - first block in (valid @ start) .first_out (first_block_quant), // output reg - valid @ ds .di (dct_out[12:0]), // input[12:0] - pixel data in (signed) .do (quant_do[12:0]), // output[12:0] - pixel data out (AC is only 9 bits long?) - changed to 10 .dv (), // output reg - data out valid .ds (quant_ds), // output reg - data out strobe (one ahead of the start of dv) .dc_tdo (quant_dc_tdo[15:0]), // output[15:0] reg - MSB aligned coefficient for the DC component (used in focus module) .dcc_en (dcc_en), // input - enable dcc (sync to beginning of a new frame) .hfc_sel (hfc_sel), // input[2:0] - hight frequency components select [2:0] (includes components with both numbers >=hfc_sel .color_first (color_first), // input - first MCU in a frame .coring_num (coring_num), // input[2:0] - coring table pair number (0..7) .dcc_vld (dccvld), // output reg - single cycle when dcc_data is valid .dcc_data (), // output[15:0] - dc component data out (for reading by software) .n000 (n000), // input[7:0] - number of zero pixels (255 if 256) - to be multiplexed with dcc .n255 (n255) // input[7:0] - number of 0xff pixels (255 if 256) - to be multiplexed with dcc ); /* /* xdct i_xdct ( .clk(clk), // top level module xdct i_xdct ( .clk(clk), // top level module Loading
compressor_jp/quantizer393.v 0 → 100644 +363 −0 Original line number Original line Diff line number Diff line /* ** -----------------------------------------------------------------------------** ** quantizator353.v ** ** Quantizer module for JPEG compressor ** ** Copyright (C) 2002-2015 Elphel, Inc ** ** -----------------------------------------------------------------------------** ** quantizer393.v is free software - hardware description language (HDL) code. ** ** This program 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. ** ** This program 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/>. ** -----------------------------------------------------------------------------** ** */ `timescale 1ns/1ps // will add extracted DC (8 bits) to data from DCT here that will make data 12 bits (signed) long. // It will be possible to make a sequintial multiplier for DC - but I'll skip this now. module quantizer393( input clk, // pixel clock, posedge input en, // enable (0 resets counter) input sclk, // system clock, twqe, twce, ta,tdi - valid @posedge (ra, tdi - 2 cycles ahead (was negedge) input twqe, // enable write to a quantization table input twce, // enable write to a coring table input [ 8:0] ta, // [8:0] table address input [15:0] tdi, // [15:0] table data in (8 LSBs - quantization data) input ctypei, // component type input (Y/C) input [ 8:0] dci, // [7:0] - average value in a block - subtracted before DCT. now normal signed number input first_stb, //this is first stb pulse in a frame input stb, // strobe that writes ctypei, dci input [ 2:0] tsi, // table (quality) select [2:0] input pre_start,// marks first input pixel (one before) input first_in, // first block in (valid @ start) output reg first_out, // valid @ ds input [12:0] di, // [11:0] pixel data in (signed) output [12:0] do, // [11:0] pixel data out (AC is only 9 bits long?) - changed to 10 output reg dv, // data out valid output reg ds, // data out strobe (one ahead of the start of dv) output reg [15:0] dc_tdo, //[15:0], MSB aligned coefficient for the DC component (used in focus module) input dcc_en, // enable dcc (sync to beginning of a new frame) input [ 2:0] hfc_sel, // hight frequency components select [2:0] (includes components with both numbers >=hfc_sel // hfc_sel == 3'h7 - now high frequency output - just 3 words - brightness and 2 color diffs input color_first, // first MCU in a frame input [ 2:0] coring_num, // coring table pair number (0..7) output reg dcc_vld, // single cycle when dcc_data is valid output [15:0] dcc_data, // [15:0] dc component data out (for reading by software) input [ 7:0] n000, // input [7:0] number of zero pixels (255 if 256) - to be multiplexed with dcc input [ 7:0] n255); // input [7:0] number of 0xff pixels (255 if 256) - to be multiplexed with dcc wire [3:0] tdco; // coring table output reg [3:0] tbac; // coring memory table number (LSB - color) reg coring_range; // input <16, use coring LUT wire [15:0] tdo; reg [ 9:0] tba; // table output (use) address wire [15:0] zigzag_q; reg wpage; reg rpage; wire [ 5:0] zwa; reg [ 5:0] zra; reg [12:0] qdo; reg [12:0] qdo0; reg zwe; reg [12:0] d1; reg [12:0] d2,d3; // registered data in, converted to sign+ absolute value wire [27:0] qmul; wire start_a; reg [15:0] tdor; reg [20:0] qmulr; // added 7 bits to total8 fractional for biasing/zero bin wire start_out; wire start_z; reg [ 8:0] dc1; // registered DC average - with restored sign // for fifo for ctype, dc wire ctype; wire [ 8:0] dc; wire next_dv; reg [ 5:0] start; wire dcc_stb; reg dcc_run; reg dcc_first; reg dcc_Y; reg [ 1:0] ctype_prev; reg [12:0] dcc_acc; reg [12:0] hfc_acc; wire hfc_en; reg hfc_copy; // copy hfc_acc to dcc_acc wire [10:0] d2_dct; // 11 bits enough, convetred to positive (before - 0 was in the middle - pixel value 128) - dcc only reg sel_satnum; // select saturation numbers - dcc only reg twqe_d; //twqe delayed (write MSW) reg twce_d; //twce delayed (write MSW) reg [15:0] pre_dc_tdo; wire copy_dc_tdo; reg first_interm; // valid @ ds wire [ 2:0] ts; wire [ 2:0] coring_sel; reg [ 2:0] block_mem_ra; reg [ 2:0] block_mem_wa; reg [ 2:0] block_mem_wa_save; reg [15:0] block_mem[0:7]; wire [15:0] block_mem_o=block_mem[block_mem_ra[2:0]]; assign dc[8:0] = block_mem_o[8:0]; assign ctype = block_mem_o[9]; assign ts[2:0] = block_mem_o[12:10]; assign coring_sel[2:0] = block_mem_o[15:13]; assign start_a = start[5]; assign start_z = start[4]; assign dcc_stb = start[2]; always @ (posedge clk) begin if (stb) block_mem[block_mem_wa[2:0]] <= {coring_num[2:0],tsi[2:0], ctypei, dci[8:0]}; if (!en) block_mem_wa[2:0] <= 3'h0; else if (stb) block_mem_wa[2:0] <= block_mem_wa[2:0] +1; if (stb && first_stb) block_mem_wa_save[2:0] <= block_mem_wa[2:0]; if (!en) block_mem_ra[2:0] <= 3'h0; else if (pre_start) block_mem_ra[2:0] <= first_in?block_mem_wa_save[2:0]:(block_mem_ra[2:0] +1); end assign d2_dct[10:0]={!d2[11] ^ ctype_prev[0], d2[9:0]}; assign dcc_data[15:0]=sel_satnum? {n255[7:0],n000[7:0]}: {dcc_first || (!dcc_Y && dcc_acc[12]) ,(!dcc_Y && dcc_acc[12]), (!dcc_Y && dcc_acc[12]), dcc_acc[12:0]}; assign do[12:0]=zigzag_q[12:0]; assign qmul[27:0]=tdor[15:0]*d3[11:0]; assign start_out = zwe && (zwa[5:0]== 6'h3f); //adjust? assign copy_dc_tdo = zwe && (zwa[5:0]== 6'h37); // not critical assign next_dv=en && (ds || (dv && (zra[5:0]!=6'h00))); always @ (posedge clk) begin d1[12:0] <= di[12:0]; //inv_sign dc1[8:0] <= start[0]?dc[8:0]:9'b0; // sync to d1[8:0]ctype valid at start, not later d2[12:0] <= {dc1[8],dc1[8:0],3'b0} + d1[12:0]; d3[12] <= d2[12]; d3[11:0] <= d2[12]? -d2[11:0]:d2[11:0]; if (start[0] || !en) tba[9:6] <= {ts[2:0],ctype}; /// TODO - make sure ctype switches at needed time (compensate if needed) ***************************************** if (start[3] || !en) tbac[3:0] <= {coring_sel[2:0],ctype}; // table number to use if (start[0]) tba[5:0] <= 6'b0; else if (tba[5:0]!=6'h3f) tba[5:0] <= tba[5:0]+1; tdor[15:0] <= tdo[15:0]; // registered table data out if (start[3]) pre_dc_tdo[15:0] <= tdor[15:0]; //16-bit q. tables) if (copy_dc_tdo) dc_tdo[15:0] <= pre_dc_tdo[15:0]; qmulr[19:0] <= qmul[27:8]; // absolute value qmulr[20] <= d3[12]; // sign qdo0[12] <= qmulr[20]; // sign // tdco[3:0] - same timing as qdo0; // use lookup table from 8 bits of absolute value (4.4 - 4 fractional) to calculate 4 bit coring output that would replace output // if input is less thahn 16. For larger values the true rounding will be used. // Absolute values here have quantization coefficients already applied, so we can use the same coring table for all DCT coefficients. // there are be 16 tables - 8 Y/C pairs to switch qdo0[11:0] <= qmulr[19:8] + qmulr[7]; // true rounding of the absolute value coring_range<= !(|qmulr[19:12]) && !(&qmulr[11:7]) ; // valid with qdo0 qdo[11:0] <= coring_range? (qdo0[12]?-{8'h0,tdco[3:0]}:{8'h0,tdco[3:0]}):(qdo0[12]?-qdo0[11:0]:qdo0[11:0]); qdo[12] <= qdo0[12] && (!coring_range || (tdco[3:0]!=4'h0)); if (start_out) rpage <= wpage; if (start_out) zra[5:0] <= 6'b0; else if (zra[5:0]!=6'h3f) zra[5:0] <= zra[5:0]+1; // conserving energy ds <= start_out; dv <= next_dv; if (start_a) first_interm <= first_in; if (start_out) first_out <=first_interm; // zwe??? zwe <= en && (start_a || (zwe && (zwa[5:0]!=6'h3f))); if (!en) wpage <= 1'b0; else if (start_a) wpage <= ~wpage; end always @ (posedge clk) begin sel_satnum <= dcc_run && (start[0]? (ctype_prev[1:0]==2'b10): sel_satnum); hfc_copy <= dcc_run && (hfc_sel[2:0]!=3'h7) && (tba[5:0]==6'h1f) && ctype_prev[0] && ctype_prev[1]; start[5:0] <= {start[4:0], pre_start}; // needed? if (!dcc_en) dcc_run <= 1'b0; else if (start[0]) dcc_run <= 1'b1; if (!dcc_en) ctype_prev[1:0] <= 2'b11; else if (start[0]) ctype_prev[1:0] <= {ctype_prev[0],ctype && dcc_run}; if (dcc_stb || hfc_copy) dcc_acc[12:0] <= hfc_copy? hfc_acc[12:0]: {(d2_dct[10]&&ctype_prev[0]),(d2_dct[10]&&ctype_prev[0]),d2_dct[10:0]}+((ctype_prev[0] || ctype_prev[1])?13'h0:dcc_acc[12:0]); if (!dcc_run || hfc_copy) hfc_acc <=13'b0; else if (hfc_en) hfc_acc <= hfc_acc + {2'b0, d3[10:0]}; if (dcc_stb) dcc_first <= color_first && dcc_run && dcc_stb && ctype && !ctype_prev[0]; if (dcc_stb) dcc_Y <= dcc_run && dcc_stb && ctype && !ctype_prev[0]; dcc_vld <= (dcc_run && dcc_stb && (ctype || ctype_prev[0] || sel_satnum)) || hfc_copy; end always @ (posedge sclk) begin twqe_d <= twqe; twce_d <= twce; end // SRL16 i_hfc_en (.Q(hfc_en), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(clk), // .D(((tba[2:0]>hfc_sel[2:0]) || (tba[5:3]>hfc_sel[2:0])) && dcc_run && !ctype_prev[0])); // dly=1+1 dly_16 #(.WIDTH(1)) i_hfc_en ( .clk(clk), .rst(1'b0), .dly(1), .din(((tba[2:0]>hfc_sel[2:0]) || (tba[5:3]>hfc_sel[2:0])) && dcc_run && !ctype_prev[0]), .dout(hfc_en)); // dly=1+1 zigzag393 i_zigzag( .clk(clk), .start(start_z), .q(zwa[5:0])); // All memories below are non-registered, see if they can be made registered ram18_var_w_var_r #( .REGISTERS (0), .LOG2WIDTH_WR (4), .LOG2WIDTH_RD (4), .DUMMY (0) ) i_quant_table ( .rclk (clk), // input .raddr ({tba[9:6],tba[2:0],tba[5:3]}), // input[8:0] .ren (1'b1), // input .regen (1'b0), // input .data_out (tdo[15:0]), // output[15:0] .wclk (sclk), // input .waddr ({ta[8:0],twqe_d}), // input[8:0] .we (twqe || twqe_d), // input .web (4'hf), // input[3:0] .data_in (tdi[15:0]) // input[15:0] ); ram18_var_w_var_r #( .REGISTERS (0), .LOG2WIDTH_WR (4), .LOG2WIDTH_RD (2), .DUMMY (0) ) i_coring_table ( .rclk (clk), // input .raddr ({tbac[3:0],qmulr[11:4]}), // input[10:0] .ren (1'b1), // input .regen (1'b0), // input .data_out (tdco[3:0]), // output[3:0] .wclk (sclk), // input .waddr ({ta[8:0],twce_d}), // input[9:0] .we (twce || twce_d), // input .web (4'hf), // input[3:0] .data_in (tdi[15:0]) // input[15:0] ); ram18_var_w_var_r #( .REGISTERS (0), .LOG2WIDTH_WR (4), .LOG2WIDTH_RD (4), .DUMMY (0) ) i_zigzagbuf ( .rclk (clk), // input .raddr ({3'b0,rpage,zra[5:0]}), // input[8:0] .ren (next_dv), // input .regen (1'b0), // input .data_out (zigzag_q[15:0]), // output[31:0] .wclk (clk), // input .waddr ({3'b0,wpage,zwa[5:0]}), // input[8:0] .we (zwe), // input .web (4'hf), // input[3:0] .data_in ({3'b0,qdo[12:0]}) // input[31:0] ); endmodule module zigzag393 ( input clk, // system clock, posedge input start, output reg [5:0] q); reg [5:0] a; wire [ 4:0] rom_a; reg [ 5:0] rom_q; assign rom_a[4:0]=a[5]?(~a[4:0]):a[4:0]; always @ (posedge clk) begin if (start) a[5:0] <= 6'b0; else if (a[5:0]!=6'h3f) a[5:0] <= a[5:0]+1; end // ROM (combinatorial) always @(rom_a) case (rom_a) 5'h00: rom_q <= 6'h00; 5'h01: rom_q <= 6'h02; 5'h02: rom_q <= 6'h03; 5'h03: rom_q <= 6'h09; 5'h04: rom_q <= 6'h0a; 5'h05: rom_q <= 6'h14; 5'h06: rom_q <= 6'h15; 5'h07: rom_q <= 6'h23; 5'h08: rom_q <= 6'h01; 5'h09: rom_q <= 6'h04; 5'h10: rom_q <= 6'h08; 5'h11: rom_q <= 6'h0b; 5'h12: rom_q <= 6'h13; 5'h13: rom_q <= 6'h16; 5'h14: rom_q <= 6'h22; 5'h15: rom_q <= 6'h24; 5'h16: rom_q <= 6'h05; 5'h17: rom_q <= 6'h07; 5'h18: rom_q <= 6'h0c; 5'h19: rom_q <= 6'h12; 5'h20: rom_q <= 6'h17; 5'h21: rom_q <= 6'h21; 5'h22: rom_q <= 6'h25; 5'h23: rom_q <= 6'h30; 5'h24: rom_q <= 6'h06; 5'h25: rom_q <= 6'h0d; 5'h26: rom_q <= 6'h11; 5'h27: rom_q <= 6'h18; 5'h28: rom_q <= 6'h20; 5'h29: rom_q <= 6'h26; 5'h30: rom_q <= 6'h2f; 5'h31: rom_q <= 6'h31; endcase // add symmetrical part always @ (posedge clk) q[5:0] <= a[5]? (~rom_q[5:0]):rom_q[5:0]; endmodule
py393/.settings/org.eclipse.core.resources.prefs +1 −0 Original line number Original line Diff line number Diff line eclipse.preferences.version=1 eclipse.preferences.version=1 encoding/convert_zigzag_rom.py=utf-8 encoding/exp_gpio.py=utf-8 encoding/exp_gpio.py=utf-8 encoding/import_verilog_parameters.py=utf-8 encoding/import_verilog_parameters.py=utf-8 encoding/mon_gpio.py=utf-8 encoding/mon_gpio.py=utf-8 Loading