Commit 4152a851 authored by Andrey Filippov's avatar Andrey Filippov

cleaning up handling exceptions in compressor, adding output FIFO

parent db90602d
...@@ -132,7 +132,9 @@ module cmprs_cmd_decode#( ...@@ -132,7 +132,9 @@ module cmprs_cmd_decode#(
parameter CMPRS_CSAT_CB_BITS = 10, // number of bits in blue scale field in color saturation word parameter CMPRS_CSAT_CB_BITS = 10, // number of bits in blue scale field in color saturation word
parameter CMPRS_CSAT_CR = 12, // bit # of number of red scale field in color saturation word parameter CMPRS_CSAT_CR = 12, // bit # of number of red scale field in color saturation word
parameter CMPRS_CSAT_CR_BITS = 10, // number of bits in red scale field in color saturation word parameter CMPRS_CSAT_CR_BITS = 10, // number of bits in red scale field in color saturation word
parameter CMPRS_CORING_BITS = 3 // number of bits in coring mode parameter CMPRS_CORING_BITS = 3, // number of bits in coring mode
parameter CMPRS_STUFFER_NEG = 1 // stuffer runs @ negedge xclk2x
)( )(
...@@ -160,7 +162,8 @@ module cmprs_cmd_decode#( ...@@ -160,7 +162,8 @@ module cmprs_cmd_decode#(
// cmprs_run should be off // cmprs_run should be off
output reg sigle_frame_buf, // memory controller uses a single frame buffer (frame_number_* == 0), use other sync output reg sigle_frame_buf, // memory controller uses a single frame buffer (frame_number_* == 0), use other sync
// outputs sync @ posedge xclk: // outputs sync @ posedge xclk:
output reg cmprs_en_xclk, // enable compressor, extends control fields for graceful shutdown output reg cmprs_en_xclk, // enable compressor, turne off immedaitely
output reg cmprs_en_late_xclk, // enable stuffer, extends control fields for graceful shutdown
// cmprs_start, // single cycle when single or constant compression is turned on // cmprs_start, // single cycle when single or constant compression is turned on
// cmprs_repeat,// high in repetitive mode // cmprs_repeat,// high in repetitive mode
// outputs @posedge xclk, frozen when the new frame is requested // outputs @posedge xclk, frozen when the new frame is requested
...@@ -291,7 +294,8 @@ module cmprs_cmd_decode#( ...@@ -291,7 +294,8 @@ module cmprs_cmd_decode#(
// re-clock to compressor clock // re-clock to compressor clock
always @ (posedge xclk) if (ctrl_we_xclk) begin always @ (posedge xclk) if (ctrl_we_xclk) begin
cmprs_en_xclk <= cmprs_en_mclk_r || cmprs_en_extend; cmprs_en_xclk <= cmprs_en_mclk_r;
cmprs_en_late_xclk <= cmprs_en_mclk_r || cmprs_en_extend;
cmprs_qpage_xclk <= cmprs_qpage_mclk; cmprs_qpage_xclk <= cmprs_qpage_mclk;
cmprs_dcsub_xclk <= cmprs_dcsub_mclk; cmprs_dcsub_xclk <= cmprs_dcsub_mclk;
cmprs_mode_xclk <= cmprs_mode_mclk; cmprs_mode_xclk <= cmprs_mode_mclk;
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
module cmprs_frame_sync#( module cmprs_frame_sync#(
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter LAST_FRAME_BITS= 16 // number of bits in frame counter (before rolls over) parameter LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
parameter CMPRS_TIMEOUT_BITS= 12,
parameter CMPRS_TIMEOUT= 1000 // mclk cycles
)( )(
input rst, input rst,
...@@ -54,8 +56,17 @@ module cmprs_frame_sync#( ...@@ -54,8 +56,17 @@ module cmprs_frame_sync#(
input [LAST_FRAME_BITS-1:0] frame_number, // current frame number (for multi-frame ranges) in this (compressor channel input [LAST_FRAME_BITS-1:0] frame_number, // current frame number (for multi-frame ranges) in this (compressor channel
input frame_done, // input - single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory input frame_done, // input - single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
output reg suspend, // suspend reading data for this channel - waiting for the source data output reg suspend, // suspend reading data for this channel - waiting for the source data
output reg broken_frame // next frame start came before previous frame was read to compressor
input stuffer_running, // @xclk2x stuffer is running/flushing
output reg force_flush_long // force flush (abort frame), can be any clock and may last until stuffer_done_mclk
// stuffer will re-clock and extract 0->1 transition
); );
/*
Abort frame (force flush) if:
a) "broken frame" - attempted to start a new frame before previous one was completely read from the memory
b) turned off enable while frame was being compressed
Abort frame lasts until flush end or timeout expire
*/
wire vsync_late_mclk; // single mclk cycle, reclocked from vsync_late wire vsync_late_mclk; // single mclk cycle, reclocked from vsync_late
wire frame_started_mclk; wire frame_started_mclk;
reg bonded_mode; reg bonded_mode;
...@@ -65,9 +76,39 @@ module cmprs_frame_sync#( ...@@ -65,9 +76,39 @@ module cmprs_frame_sync#(
reg line_numbers_sync; // src unfinished line number is > this unfinished line number reg line_numbers_sync; // src unfinished line number is > this unfinished line number
reg reading_frame; // compressor is reading frame data (make sure input is done before starting next frame, otherwise make it a broken frame reg reading_frame; // compressor is reading frame data (make sure input is done before starting next frame, otherwise make it a broken frame
reg broken_frame;
reg aborted_frame;
reg stuffer_running_mclk;
reg [CMPRS_TIMEOUT_BITS-1:0] timeout;
reg cmprs_en_extend_r=0;
reg cmprs_en_d;
assign frame_start_dst = frame_start_dst_r; assign frame_start_dst = frame_start_dst_r;
assign cmprs_en_extend = cmprs_en_extend_r;
always @ (posedge rst or posedge mclk) begin
if (rst) cmprs_en_extend_r <= 0;
else if (cmprs_en) cmprs_en_extend_r <= 1;
else if ((timeout == 0) || !stuffer_running_mclk) cmprs_en_extend_r <= 0;
end
always @ (posedge mclk) begin always @ (posedge mclk) begin
stuffer_running_mclk <= stuffer_running; // re-clock from negedge xclk2x
if (cmprs_en) timeout <= CMPRS_TIMEOUT;
else if (!cmprs_en_extend_r) timeout <= 0;
else timeout <= timeout - 1;
cmprs_en_d <= cmprs_en;
broken_frame <= cmprs_en && cmprs_run && vsync_late_mclk && reading_frame; // single xclk pulse
aborted_frame <= cmprs_en_d && !cmprs_en && stuffer_running_mclk;
if (!stuffer_running_mclk ||!cmprs_en_extend_r) force_flush_long <= 0;
else if (broken_frame || aborted_frame) force_flush_long <= 1;
if (!cmprs_en || frame_done || (cmprs_run && vsync_late_mclk)) reading_frame <= 0;
else if (frame_started_mclk) reading_frame <= 1;
frame_start_dst_r <= cmprs_en && (cmprs_run ? (vsync_late_mclk && !reading_frame) : cmprs_standalone); frame_start_dst_r <= cmprs_en && (cmprs_run ? (vsync_late_mclk && !reading_frame) : cmprs_standalone);
if (!cmprs_en) bonded_mode <= 0; if (!cmprs_en) bonded_mode <= 0;
else if (cmprs_run) bonded_mode <= 1; else if (cmprs_run) bonded_mode <= 1;
...@@ -82,10 +123,6 @@ module cmprs_frame_sync#( ...@@ -82,10 +123,6 @@ module cmprs_frame_sync#(
suspend <= !bonded_mode && ((sigle_frame_buf ? frames_differ : frames_numbers_differ) || line_numbers_sync); suspend <= !bonded_mode && ((sigle_frame_buf ? frames_differ : frames_numbers_differ) || line_numbers_sync);
if (!cmprs_en || frame_done || (cmprs_run && vsync_late_mclk)) reading_frame <= 0;
else if (frame_started_mclk) reading_frame <= 1;
broken_frame <= cmprs_en && cmprs_run && vsync_late_mclk && reading_frame; // single xclk pulse
end end
......
/*******************************************************************************
* Module: cmprs_out_fifo
* Date:2015-06-25
* Author: andrey
* Description: Compressor output FIFO
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmprs_out_fifo.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.
*
* cmprs_out_fifo.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 cmprs_out_fifo(
input rst, // mostly for simulation
// wclk domain
input wclk, // source clock (2x pixel clock, inverted)
input we,
input [15:0] wdata,
input wa_rst, // reset low address bits when stuffer is disabled (to make sure it is multiple of 32 bytes
input wlast, // written last 32 bytes of a frame (flush FIFO) - stuffer_done (has to be later than we)
output eof_written_wclk, // eof_written - reclocked to wclk
// rclk domain
input rclk,
input rst_fifo, // reset FIFO (set read adderss to write, reset count)
input ren,
output [63:0] rdata,
output eof, // single rclk pulse signalling EOF
input eof_written, // confirm frame written ofer AFI to the system memory (single rclk pulse)
output flush_fifo, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read)
output [7:0] fifo_count // number of 32-byte chunks in FIFO
);
reg regen;
reg [ 8:0] raddr;
reg [ 7:0] count32;
reg [ 7:0] lcount32; // counting chunks left in the same frame
reg [10:0] waddr;
wire written32b; // written 32 bytes, re-clocked to read clock domain (single-cycle)
wire wlast_rclk;
reg flush_fifo_r;
assign flush_fifo = flush_fifo_r;
assign fifo_count = count32;
assign eof = wlast_rclk;
always @ (posedge rst or posedge wclk) begin
if (rst) waddr <= 0;
else if (wa_rst) waddr <= waddr & 11'h7f0; // reset 4 LSBs only
else if (we) waddr <= waddr + 1;
end
always @ (posedge rclk) begin
regen <= ren;
if (rst_fifo) raddr <= {waddr[10:4],2'b0};
else if (ren) raddr <= raddr + 1;
if (rst_fifo) count32 <= 0;
else if ( written32b && !(ren && (&raddr[1:0]))) count32 <= count32 + 1;
else if (!written32b && (ren && (&raddr[1:0]))) count32 <= count32 - 1;
if (rst_fifo) lcount32 <= 0;
else if (wlast_rclk) lcount32 <= count32;
else if ((lcount32 !=0) && ren && (&raddr[1:0])) lcount32 <= lcount32 - 1;
if (rst_fifo) flush_fifo_r <= 0;
else if (wlast_rclk) flush_fifo_r <= 1;
else if ((count32[7:1] == 0) && ( !count32[0] || ren)) flush_fifo_r <= 0;
end
// wclk -> rclk
pulse_cross_clock written32b_i (.rst(rst), .src_clk(wclk), .dst_clk(rclk), .in_pulse(we && (&waddr[3:0])), .out_pulse(written32b),.busy());
pulse_cross_clock wlast_rclk_i (.rst(rst), .src_clk(wclk), .dst_clk(rclk), .in_pulse(wlast), .out_pulse(wlast_rclk),.busy());
// rclk -> wclk
pulse_cross_clock eof_written_wclk_i (.rst(rst), .src_clk(rclk), .dst_clk(wclk), .in_pulse(eof_written), .out_pulse(eof_written_wclk),.busy());
ram_var_w_var_r #(
.REGISTERS(1),
.LOG2WIDTH_WR(4),
.LOG2WIDTH_RD(6)
) fifo_i (
.rclk (rclk), // input
.raddr (raddr), // input[8:0]
.ren (ren), // input
.regen (regen), // input
.data_out (rdata), // output[63:0]
.wclk (wclk), // input - OK, negedge mclk
.waddr (waddr), // input[10:0]
.we (we), // input
.web (8'hff), // input[7:0]
.data_in (wdata) // input[15:0]
);
endmodule
This diff is collapsed.
...@@ -43,15 +43,16 @@ ...@@ -43,15 +43,16 @@
module stuffer393 ( module stuffer393 (
input clk, // 2x pixel clock input clk, // 2x pixel clock
input en, // enable, 0- reset input en_in, // enable, 0- reset (other clock domain, needs re-sync)
input reset_data_counters, // reset data transfer counters (only when DMA and compressor are disabled) input reset_data_counters, // reset data transfer counters (only when DMA and compressor are disabled)
input flush, // flush output data (fill byte with 0, long word with 0 input flush, // flush output data (fill byte with 0, long word with 0
input abort, // @ any, extracts 0->1 and flushes
input stb, // input data strobe input stb, // input data strobe
input [3:0] dl, // [3:0] number of bits to send (0 - 16) ?? input [3:0] dl, // [3:0] number of bits to send (0 - 16) ??
input [15:0] d, // [15:0] input data to shift (only lower bits are valid) input [15:0] d, // [15:0] input data to shift (only lower bits are valid)
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current froma, but before the next one // time stamping - will copy time at the end of color_first (later than the first hact after vact in the current froma, but before the next one
// and before the data is needed for output // and before the data is needed for output
input color_first, // input color_first, // (different clock) only used for timestamp
input [31:0] sec, // [31:0] number of seconds input [31:0] sec, // [31:0] number of seconds
input [19:0] usec, // [19:0] number of microseconds input [19:0] usec, // [19:0] number of microseconds
output rdy, // enable huffman encoder to proceed. Used as CE for many huffman encoder registers output rdy, // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
...@@ -60,7 +61,8 @@ module stuffer393 ( ...@@ -60,7 +61,8 @@ module stuffer393 (
output reg qv, // output data valid output reg qv, // output data valid
output done, // reset by !en, goes high after some delay after flushing output done, // reset by !en, goes high after some delay after flushing
output reg [23:0] imgptr, // [23:0]image pointer in 32-byte chunks output reg [23:0] imgptr, // [23:0]image pointer in 32-byte chunks
output reg flushing output reg flushing,
output reg running // from registering timestamp until done
`ifdef debug_stuffer `ifdef debug_stuffer
, output reg [3:0] etrax_dma_r, // [3:0] just for testing , output reg [3:0] etrax_dma_r, // [3:0] just for testing
output reg [3:0] test_cntr, output reg [3:0] test_cntr,
...@@ -71,7 +73,12 @@ module stuffer393 ( ...@@ -71,7 +73,12 @@ module stuffer393 (
`ifdef debug_stuffer `ifdef debug_stuffer
reg en_d; reg en_d;
`endif `endif
reg en; // re-clock en_in to match this clock
reg [2:0] abort_r;
reg force_flush;
reg [23:1] stage1; // stage 1 register (after right-shifting input data by 0..7 - actually left by 7..0) reg [23:1] stage1; // stage 1 register (after right-shifting input data by 0..7 - actually left by 7..0)
wire [2:0] shift1; // shift amount for stage 1 wire [2:0] shift1; // shift amount for stage 1
reg [4:0] stage1_bits; // number of topmost invalid bits in stage1 register - 2 MSBs, use lower 3 stage2_bits reg [4:0] stage1_bits; // number of topmost invalid bits in stage1 register - 2 MSBs, use lower 3 stage2_bits
...@@ -127,8 +134,24 @@ module stuffer393 ( ...@@ -127,8 +134,24 @@ module stuffer393 (
// stb_time[2] - single-cycle pulse after color_first goes low // stb_time[2] - single-cycle pulse after color_first goes low
reg [19:0] imgsz32; // current image size in multiples of 32-bytes reg [19:0] imgsz32; // current image size in multiples of 32-bytes
reg inc_imgsz32; reg inc_imgsz32;
// re-clock enable to this clock
always @ (negedge clk) begin
en <= en_in;
// re-clock abort, extract leading edge
abort_r <= {abort_r[0] & ~abort_r[1], abort_r[0], abort};
if (!en) force_flush <= 0;
else if (abort_r) force_flush <= 1;
else if (flush_end) force_flush <= 0;
if (!en) running <= 0;
else if (stb_time[2]) running <= 1;
else if (flush_end) running <= 0;
end
always @ (negedge clk) flushing <= en && !flush_end && ((flush && rdy) || flushing); always @ (negedge clk) begin
flushing <= en && !flush_end && (((flush || force_flush) && rdy) || flushing);
end
wire [4:0] pre_stage1_bits; wire [4:0] pre_stage1_bits;
assign pre_stage1_bits[4:0]={2'b00,stage1_bits[2:0]} + {(dl[3:0]==4'b0),dl[3:0]}; assign pre_stage1_bits[4:0]={2'b00,stage1_bits[2:0]} + {(dl[3:0]==4'b0),dl[3:0]};
......
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