Commit b040c02d authored by Andrey Filippov's avatar Andrey Filippov

continue porting compressor logic

parent 3bccc0bb
......@@ -125,14 +125,14 @@ module jp_channel#(
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 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 [ 2:0] yc_nodc_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 yc_nodc_last; // sending last_r MCU (valid @ ds)
wire dct_start; // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block
wire [ 2:0] color_tn; // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start)
wire color_first; // sending first_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)
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_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;
......@@ -293,13 +293,13 @@ module jp_channel#(
.do (yc_nodc), // output[9:0]
.avr (yc_avr), // output[8:0]
.dv (yc_nodc_dv), // output
.ds (yc_nodc_ds), // output
.tn (yc_nodc_tn), // output[2:0]
.first (yc_nodc_first), // output reg
.last (yc_nodc_last), // output reg
.ds (dct_start), // output
.tn (color_tn), // output[2:0]
.first (color_first), // output reg
.last (color_last), // output reg
.component_num (yc_nodc_component_num), // output[2:0]
.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
);
// wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0)
......@@ -309,18 +309,87 @@ module jp_channel#(
wire dct_dv;
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 (
.clk (xclk), // input
.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]
.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
.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]
);
reg quant_start;
always @ (posedge xclk) quant_start <= dct_pre_first_out;
wire quant_start;
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
......
/*
** -----------------------------------------------------------------------------**
** 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
eclipse.preferences.version=1
encoding/convert_zigzag_rom.py=utf-8
encoding/exp_gpio.py=utf-8
encoding/import_verilog_parameters.py=utf-8
encoding/mon_gpio.py=utf-8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment