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

cleaning up handling exceptions in compressor, adding output FIFO

parent db90602d
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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_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_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#(
                                                      // cmprs_run should be off
    output reg                    sigle_frame_buf,    // memory controller uses a single frame buffer (frame_number_* == 0), use other sync
                                  //  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_repeat,// high in repetitive mode
                                  // outputs @posedge xclk, frozen when the new frame is requested
@@ -291,7 +294,8 @@ module cmprs_cmd_decode#(
    // re-clock to compressor clock
    
    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_dcsub_xclk <=     cmprs_dcsub_mclk;
        cmprs_mode_xclk <=      cmprs_mode_mclk;
+44 −7
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@

module  cmprs_frame_sync#(
    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,
@@ -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                         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                    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   frame_started_mclk; 
    reg    bonded_mode;
@@ -65,9 +76,39 @@ module cmprs_frame_sync#(
    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    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 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
        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);
        if      (!cmprs_en)        bonded_mode <= 0;
        else if (cmprs_run)        bonded_mode <= 1;
@@ -82,10 +123,6 @@ module cmprs_frame_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
    
+108 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * 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
+95 −67

File changed.

Preview size limit exceeded, changes collapsed.

+28 −5
Original line number Diff line number Diff line
@@ -43,15 +43,16 @@

module stuffer393 (
    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              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        [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)
// 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 
    input              color_first, //
    input              color_first, // (different clock) only used for timestamp
    input       [31:0] sec,         // [31:0] number of seconds
    input       [19:0] usec,        // [19:0] number of microseconds
    output             rdy,         // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
@@ -60,7 +61,8 @@ module stuffer393 (
    output reg         qv,          // output data valid
    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         flushing
    output reg         flushing,
    output reg         running      // from registering timestamp until done
`ifdef debug_stuffer
,      output reg   [3:0] etrax_dma_r, // [3:0] just for testing
       output reg   [3:0] test_cntr,
@@ -71,6 +73,11 @@ module stuffer393 (
`ifdef debug_stuffer
    reg           en_d;
`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)
    wire    [2:0] shift1;        // shift amount for stage 1
@@ -127,8 +134,24 @@ module stuffer393 (
// stb_time[2] - single-cycle pulse after color_first goes low 
    reg    [19:0] imgsz32; // current image size in multiples of 32-bytes
    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;
        
    always @ (negedge clk)  flushing <= en && !flush_end && ((flush && rdy) || flushing);
    end

    always @ (negedge clk)  begin
        flushing <= en && !flush_end && (((flush || force_flush) && rdy) || flushing);
    end
    
    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]};