Commit 43f67702 authored by Andrey Filippov's avatar Andrey Filippov

ported all other submodules for the JPEG/JP4 compressor

parent b040c02d
/*******************************************************************************
* Module: dcc_sync393
* Date:2015-06-17
* Author: andrey
* Description: Synchronises output of DC components
* Syncronizes dcc data with dma1 output, adds 16..31 16-bit zero words for Axis DMA
* Was not used in late NC353 camera (DMA channel used fro IMU logger)
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* dcc_sync393.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.
*
* dcc_sync393.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/> .
*******************************************************************************/
`timescale 1ns/1ps
module dcc_sync393(
input sclk, // system clock: twe, ta,tdi - valid @negedge (ra, tdi - 2 cycles ahead)
input dcc_en, // clk rising, sync with start of the frame
input finish_dcc, // sclk rising
input dcc_vld, // clk rising
input [15:0] dcc_data, //[15:0] clk risimg
output reg statistics_dv, //sclk
output reg [15:0] statistics_do); //[15:0] sclk
reg statistics_we;
reg dcc_run;
reg dcc_finishing;
reg skip16; // output just 16 zero words (data was multiple of 16 words)
reg [ 4:0] dcc_cntr;
always @ (posedge sclk) begin
dcc_run <= dcc_en;
statistics_we <= dcc_run && dcc_vld && !statistics_we;
statistics_do[15:0] <= statistics_we?dcc_data[15:0]:16'h0;
statistics_dv <= statistics_we || dcc_finishing;
skip16 <= finish_dcc && (statistics_dv?(dcc_cntr[3:0]==4'hf):(dcc_cntr[3:0]==4'h0) );
if (!dcc_run) dcc_cntr[3:0] <= 4'h0;
else if (statistics_dv) dcc_cntr[3:0] <= dcc_cntr[3:0]+1;
dcc_cntr[4] <= dcc_run && ((dcc_finishing && ((dcc_cntr[3:0]==4'hf)^dcc_cntr[4]) || skip16));
dcc_finishing <= dcc_run && (finish_dcc || (dcc_finishing && (dcc_cntr[4:1]!=4'hf)));
end
endmodule
/*
** -----------------------------------------------------------------------------**
** encoderDCAC393.v
**
** RLL encoder for JPEG compressor
**
** Copyright (C) 2002-2015 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** encoderDCAC393.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/>.
** -----------------------------------------------------------------------------**
**
*/
// Accepts 13-bits signed data (only 12-bit can be ecoded), so DC difference (to be encoded) is limited (saturated) to 12 bits, not the value itself
// AC - always limited to 800 .. 7ff
module encoderDCAC393(
input clk, // pixel clock, posedge
input en, // enable (0 resets)
input lasti, // was "last MCU in a frame" (@ stb)
input first_blocki, // first block in frame - save fifo write address (@ stb)
input [ 2:0] comp_numberi, // [2:0] component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use (@ stb)
input comp_firsti, // first this component in a frame (reset DC) (@ stb)
input comp_colori, // use color - huffman? (@ stb)
input comp_lastinmbi, // last component in a macroblock (@ stb) is it needed?
input stb, // strobe that writes firsti, lasti, tni,average
input [12:0] zdi, // [11:0] zigzag-reordered data input
input first_blockz, // first block input (@zds)
input zds, // strobe - one ahead of the DC component output
output reg last, //
output reg [15:0] do,
output reg dv);
// 8x13 DC storage memory
reg [12:0] dc_mem[7:0];
reg [12:0] dc_diff0, dc_diff;
wire [11:0] dc_diff_limited= (dc_diff[12]==dc_diff[11])?
dc_diff[11:0] :
{~dc_diff[11],{11{dc_diff[11]}}}; // difference (to be encoded) limited to fit 12 bits
reg [12:0] dc_restored; // corrected DC value of the current block, compensated to fit difference to 12 bits
reg [ 5:0] rll_cntr;
reg [5:0] cntr;
reg [11:0] ac_in;
wire izero=(ac_in[11:0]==12'b0);
reg [14:0] val_r; // DC diff/AC values to be sent out, registered
reg DCACen; // enable DC/AC (2 cycles ahead of do
wire rll_out;
wire pre_dv;
reg was_nonzero_AC;
reg [12:0] zdi_d;
reg [3:0] zds_d;
wire DC_tosend= zds_d[2];
wire pre_DCACen= zds_d[1];
wire [2:0] comp_numbero; // [2:0] component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use
wire comp_firsto; // first this component in a frame (reset DC)
wire comp_coloro; // use color - huffman?
wire comp_lastinmbo; // last component in a macroblock
wire lasto; // last macroblock in a frame
reg [2:0] block_mem_ra;
reg [2:0] block_mem_wa;
reg [2:0] block_mem_wa_save;
reg [6:0] block_mem[0:7];
wire [6:0] block_mem_o=block_mem[block_mem_ra[2:0]];
assign comp_numbero[2:0]= block_mem_o[2:0];
assign comp_firsto= block_mem_o[3];
assign comp_coloro= block_mem_o[4];
assign comp_lastinmbo= block_mem_o[5];
assign lasto= block_mem_o[6];
always @ (posedge clk) begin
if (stb) block_mem[block_mem_wa[2:0]] <= {lasti, comp_lastinmbi, comp_colori,comp_firsti,comp_numberi[2: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_blocki) block_mem_wa_save[2:0] <= block_mem_wa[2:0];
if (!en) block_mem_ra[2:0] <= 3'h0;
else if (zds) block_mem_ra[2:0] <= first_blockz?block_mem_wa_save[2:0]:(block_mem_ra[2:0] +1);
end
assign rll_out= ((val_r[12] && !val_r[14]) || (ac_in[11:0]!=12'b0)) && (rll_cntr[5:0]!=6'b0);
assign pre_dv=rll_out || val_r[14] || was_nonzero_AC;
always @ (posedge clk) begin
val_r[14:0] <={ DC_tosend?
{en,
comp_coloro,
comp_lastinmbo && lasto, // last component's in a frame DC coefficient
dc_diff_limited[11:0]}:
{2'b0,
(cntr[5:0]==6'h3f),
ac_in[11:0]}};
was_nonzero_AC <= en && (ac_in[11:0]!=12'b0) && DCACen;
if (pre_dv) do <= rll_out? {3'b0,val_r[12],6'b0,rll_cntr[5:0]}:{1'b1,val_r[14:0]};
dv <= pre_dv;
DCACen <= en && (pre_DCACen || (DCACen && (cntr[5:0]!=6'h3f))); // adjust
if (!DCACen) cntr[5:0] <=6'b0;
else cntr[5:0] <=cntr[5:0]+1;
end
always @ (posedge clk) begin
zdi_d[12:0] <= zdi[12:0];
ac_in[11:0] <= (zdi_d[12]==zdi_d[11])? zdi_d[11:0]:{~zdi_d[11],{11{zdi_d[11]}}}; // always // delay + saturation
if (DC_tosend || !izero || !DCACen) rll_cntr[5:0] <= 6'h0;
else if (DCACen) rll_cntr[5:0] <= rll_cntr[5:0] +1 ;
if (DC_tosend) last <= lasto;
end
// DC components
always @ (posedge clk) begin
zds_d[3:0] <= {zds_d[2:0], zds};
if (zds_d[0]) dc_diff0[12:0] <= comp_firsto?13'b0:dc_mem[comp_numbero[2:0]];
if (zds_d[1]) dc_diff [12:0] <= zdi_d[12:0]-dc_diff0[12:0];
if (zds_d[2]) dc_restored[12:0] <= dc_diff0[12:0] + {dc_diff_limited[11],dc_diff_limited[11:0]};
if (zds_d[3]) dc_mem[comp_numbero[2:0]] <= dc_restored[12:0];
end
// Generate output stream to facilitate huffman encoding. The data will go to FIFO (16x) to compensate for possible long Huffman codes
// and/or zero-byte insertions
// format:
// {2'b11, color,last block, dc[11:0]} - DC data
// {2'b10, 1'b0, last coeff, ac[11:0]} - AC data (last coeff is set if it is last- 63-rd AC coefficient)
// {2'h00, 2'b00, 6'b0,rll[ 5:0]} - RLL zeroes.
// {2'h00, 2'b01, 6'b0,rll[ 5:0]} - end of block. lower 6 bits will have length that should be ignored
endmodule
This diff is collapsed.
/*
** -----------------------------------------------------------------------------**
** huff_fifo393.v
**
** Part of Huffman encoder for JPEG compressor - FIFO for Huffman encoder
**
** Copyright (C) 2002-2015 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** huff_fifo393.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/>.
** -----------------------------------------------------------------------------**
**
*/
//used the other edge of the clk2x
module huff_fifo393 (
input xclk, // pixel clock, posedge
input xclk2x, // twice frequency - uses negedge inside
input en, // will reset if ==0 (sync to xclk)
input [15:0] di, // data in (sync to xclk)
input ds, // din valid (sync to xclk)
input want_read,
input want_read_early,
output reg dav, // FIFO output latch has data (fifo_or_full)
output reg [15:0] q_latch); // output data
reg [9:0] wa;
reg [9:0] sync_wa; // delayed wa, re_latch-calculated at output clock
reg [9:0] ra_r;
reg [9:0] ra_latch;
reg load_q;
wire [15:0] fifo_o;
reg ds1; // ds delayed by one xclk to give time to block ram to write data. Not needed likely.
reg synci;
reg [1:0] synco;
reg sync_we; // single xclk2x period pulse for each ds@xclk
reg en2x; // en sync to xclk2x;
reg re_r;
reg re_latch;
reg fifo_dav; // RAM output reg has data
reg dav_and_fifo_dav;
wire ram_dav; // RAM has data inside
reg [9:0] diff_a;
wire next_re;
always @ (posedge xclk) begin // input stage, no overrun detection
if (!en) wa[9:0] <= 10'b0;
else if (ds) wa[9:0] <= wa[9:0]+1;
ds1 <= ds && en;
if (!en) synci <= 1'b0;
else if (ds1) synci <= ~synci;
end
always @ (negedge xclk2x) begin
en2x <= en;
synco[1:0] <= {synco[0],synci};
sync_we <= en2x && (synco[0] != synco[1]);
end
assign ram_dav= sync_we || (diff_a[9:0] != 10'b0);
assign next_re= ram_dav && (!dav_and_fifo_dav || want_read);
always @ (negedge xclk2x) begin
dav <= en2x && (fifo_dav || (dav && !want_read));
fifo_dav <= en2x && (ram_dav ||(dav && fifo_dav && !want_read));
dav_and_fifo_dav <= en2x && (fifo_dav || (dav && !want_read)) && (ram_dav ||(dav && fifo_dav && !want_read)); // will optimize auto
re_r <= en2x && next_re;
if (!en2x) sync_wa[9:0] <= 10'b0;
else if (sync_we) sync_wa[9:0] <= sync_wa[9:0]+1;
if (!en2x) ra_r [9:0] <= 10'b0;
else if (next_re) ra_r [9:0] <= ra_r[9:0]+1;
if (!en2x) diff_a[9:0] <= 10'b0;
else if (sync_we && !next_re) diff_a[9:0] <= diff_a[9:0]+1;
else if (!sync_we && next_re) diff_a[9:0] <= diff_a[9:0]-1;
end
/*
LD i_re (.Q(re_latch),.G(xclk2x),.D(next_re));
LD i_ra9 (.Q(ra_latch[9]),.G(xclk2x),.D(ra_r[9]));
LD i_ra8 (.Q(ra_latch[8]),.G(xclk2x),.D(ra_r[8]));
LD i_ra7 (.Q(ra_latch[7]),.G(xclk2x),.D(ra_r[7]));
LD i_ra6 (.Q(ra_latch[6]),.G(xclk2x),.D(ra_r[6]));
LD i_ra5 (.Q(ra_latch[5]),.G(xclk2x),.D(ra_r[5]));
LD i_ra4 (.Q(ra_latch[4]),.G(xclk2x),.D(ra_r[4]));
LD i_ra3 (.Q(ra_latch[3]),.G(xclk2x),.D(ra_r[3]));
LD i_ra2 (.Q(ra_latch[2]),.G(xclk2x),.D(ra_r[2]));
LD i_ra1 (.Q(ra_latch[1]),.G(xclk2x),.D(ra_r[1]));
LD i_ra0 (.Q(ra_latch[0]),.G(xclk2x),.D(ra_r[0]));
*/
always @* if (xclk2x) re_latch <= next_re;
always @* if (xclk2x) ra_latch <= ra_r;
always @ (posedge xclk2x) begin
load_q <= dav?want_read_early:re_r;
end
/*
LD_1 i_q15 (.Q( q_latch[15]),.G(xclk2x),.D(load_q?fifo_o[15]:q_latch[15]));
LD_1 i_q14 (.Q( q_latch[14]),.G(xclk2x),.D(load_q?fifo_o[14]:q_latch[14]));
LD_1 i_q13 (.Q( q_latch[13]),.G(xclk2x),.D(load_q?fifo_o[13]:q_latch[13]));
LD_1 i_q12 (.Q( q_latch[12]),.G(xclk2x),.D(load_q?fifo_o[12]:q_latch[12]));
LD_1 i_q11 (.Q( q_latch[11]),.G(xclk2x),.D(load_q?fifo_o[11]:q_latch[11]));
LD_1 i_q10 (.Q( q_latch[10]),.G(xclk2x),.D(load_q?fifo_o[10]:q_latch[10]));
LD_1 i_q9 (.Q( q_latch[ 9]),.G(xclk2x),.D(load_q?fifo_o[ 9]:q_latch[ 9]));
LD_1 i_q8 (.Q( q_latch[ 8]),.G(xclk2x),.D(load_q?fifo_o[ 8]:q_latch[ 8]));
LD_1 i_q7 (.Q( q_latch[ 7]),.G(xclk2x),.D(load_q?fifo_o[ 7]:q_latch[ 7]));
LD_1 i_q6 (.Q( q_latch[ 6]),.G(xclk2x),.D(load_q?fifo_o[ 6]:q_latch[ 6]));
LD_1 i_q5 (.Q( q_latch[ 5]),.G(xclk2x),.D(load_q?fifo_o[ 5]:q_latch[ 5]));
LD_1 i_q4 (.Q( q_latch[ 4]),.G(xclk2x),.D(load_q?fifo_o[ 4]:q_latch[ 4]));
LD_1 i_q3 (.Q( q_latch[ 3]),.G(xclk2x),.D(load_q?fifo_o[ 3]:q_latch[ 3]));
LD_1 i_q2 (.Q( q_latch[ 2]),.G(xclk2x),.D(load_q?fifo_o[ 2]:q_latch[ 2]));
LD_1 i_q1 (.Q( q_latch[ 1]),.G(xclk2x),.D(load_q?fifo_o[ 1]:q_latch[ 1]));
LD_1 i_q0 (.Q( q_latch[ 0]),.G(xclk2x),.D(load_q?fifo_o[ 0]:q_latch[ 0]));
*/
always @* if (~xclk2x) begin
if (load_q) q_latch <= fifo_o;
end
/*
RAMB16_S18_S18 i_fifo (
.DOA(), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA(wa[9:0]), // Port A 10-bit Address Input
.CLKA(xclk), // Port A Clock
.DIA(di[15:0]), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(ds), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(fifo_o[15:0]),// Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB(ra_latch[9:0]), // Port B 10-bit Address Input
.CLKB(xclk2x), // Port B Clock
.DIB(16'b0), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(re_latch), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
*/
ram18_var_w_var_r #(
.REGISTERS (0),
.LOG2WIDTH_WR (4),
.LOG2WIDTH_RD (4),
.DUMMY (0)
) i_fifo (
.rclk (xclk2x), // input
.raddr (ra_latch[9:0]), // input[9:0]
.ren (re_latch), // input
.regen (1'b1), // input
.data_out (fifo_o[15:0]), // output[15:0]
.wclk (xclk), // input
.waddr (wa[9:0]), // input[9:0]
.we (ds), // input
.web (4'hf), // input[3:0]
.data_in (di[15:0]) // input[15:0]
);
endmodule
This diff is collapsed.
This diff is collapsed.
...@@ -258,7 +258,7 @@ module quantizer393( ...@@ -258,7 +258,7 @@ module quantizer393(
.rclk (clk), // input .rclk (clk), // input
.raddr ({tba[9:6],tba[2:0],tba[5:3]}), // input[8:0] .raddr ({tba[9:6],tba[2:0],tba[5:3]}), // input[8:0]
.ren (1'b1), // input .ren (1'b1), // input
.regen (1'b0), // input .regen (1'b1), // input
.data_out (tdo[15:0]), // output[15:0] .data_out (tdo[15:0]), // output[15:0]
.wclk (sclk), // input .wclk (sclk), // input
.waddr ({ta[8:0],twqe_d}), // input[8:0] .waddr ({ta[8:0],twqe_d}), // input[8:0]
...@@ -276,7 +276,7 @@ module quantizer393( ...@@ -276,7 +276,7 @@ module quantizer393(
.rclk (clk), // input .rclk (clk), // input
.raddr ({tbac[3:0],qmulr[11:4]}), // input[10:0] .raddr ({tbac[3:0],qmulr[11:4]}), // input[10:0]
.ren (1'b1), // input .ren (1'b1), // input
.regen (1'b0), // input .regen (1'b1), // input
.data_out (tdco[3:0]), // output[3:0] .data_out (tdco[3:0]), // output[3:0]
.wclk (sclk), // input .wclk (sclk), // input
.waddr ({ta[8:0],twce_d}), // input[9:0] .waddr ({ta[8:0],twce_d}), // input[9:0]
...@@ -294,7 +294,7 @@ module quantizer393( ...@@ -294,7 +294,7 @@ module quantizer393(
.rclk (clk), // input .rclk (clk), // input
.raddr ({3'b0,rpage,zra[5:0]}), // input[8:0] .raddr ({3'b0,rpage,zra[5:0]}), // input[8:0]
.ren (next_dv), // input .ren (next_dv), // input
.regen (1'b0), // input .regen (1'b1), // input
.data_out (zigzag_q[15:0]), // output[31:0] .data_out (zigzag_q[15:0]), // output[31:0]
.wclk (clk), // input .wclk (clk), // input
.waddr ({3'b0,wpage,zwa[5:0]}), // input[8:0] .waddr ({3'b0,wpage,zwa[5:0]}), // input[8:0]
......
This diff is collapsed.
/*
** -----------------------------------------------------------------------------**
** varlen_encode393.v
**
** Part of the Huffman encoder for JPEG compressor - variable length encoder
**
** Copyright (C) 2002-2015 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** varlen_encode393.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/>.
** -----------------------------------------------------------------------------**
**
*/
//used the other edge of the clk2x
// Encoder will work 2 cycles/"normal" word, 1 cycle for codes "00" and "f0",
// only magnitude output is needed ASAP (2 cycles, the value out should be
// valid on the 5-th cycle - it will latency 4 cycles run each other cycle
// I'll make a shortcut - all codes processed in 2 cycles.
module varlen_encode393 (
input clk, // twice frequency - uses negedge inside
input en, // will enable registers. 0 - freeze at once
input start, // (not faster than each other cycle)
input [11:0] d, // 12-bit signed
output reg [3:0] l, // [3:0] code length
output reg [3:0] l_late,// delayed l (sync to q)
output reg [10:0] q); // [10:0]code
/*
varlen_encode393 i_varlen_encode(.clk(clk),
.en(stuffer_was_rdy), //will enable registers. 0 - freeze
.start(steps[0]),
.d(sval[11:0]), // 12-bit signed
.l(var_dl[ 3:0]), // [3:0] code length
.l_late(var_dl_late[3:0]),
.q(var_do[10:0])); // [10:0]code
*/
reg [11:0] d1;
reg [10:0] q0;
reg [2:0] cycles;
wire this0 = |d1[ 3:0];
wire this1 = |d1[ 7:4];
wire this2 = |d1[10:8];
wire [1:0] codel0 = {|d1[ 3: 2],d1[ 3] || (d1[ 1] & ~d1[ 2])};
wire [1:0] codel1 = {|d1[ 7: 6],d1[ 7] || (d1[ 5] & ~d1[ 6])};
wire [1:0] codel2 = {|d1[ 10], (d1[ 9] & ~d1[10])};
wire [3:0] codel = this2? {2'b10,codel2[1:0]} :
(this1? {2'b01, codel1[1:0]} :
(this0 ? {2'b00,codel0[1:0]} : 4'b1111)); // after +1 will be 0;
always @ (negedge clk) if (en) begin
cycles[2:0] <= {cycles[1:0],start};
end
always @ (negedge clk) if (en && start) begin
d1[ 11] <= d[11];
d1[10:0] <= d[11]?-d[10:0]:d[10:0];
end
always @ (negedge clk) if (en & cycles[0]) begin
q0[10:0] <= d1[11]?~d1[10:0]:d1[10:0];
l <= codel[3:0]+1; // needed only ASAP, valid only 2 cycles after start
end
always @ (negedge clk) if (en & cycles[2]) begin
q[10:0] <= q0[10:0];
l_late[3:0] <= l[3:0];
end
endmodule
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