Commit b040c02d authored by Andrey Filippov's avatar Andrey Filippov
Browse files

continue porting compressor logic

parent 3bccc0bb
Loading
Loading
Loading
Loading
+82 −13
Original line number Original line Diff line number Diff line
@@ -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;




@@ -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)
@@ -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
+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
+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