Commit 18addecb authored by Andrey Filippov's avatar Andrey Filippov
Browse files

added status generation module for cmprs_afi_mux

parent d2699ad8
Loading
Loading
Loading
Loading
+110 −11
Original line number Original line Diff line number Diff line
@@ -21,6 +21,17 @@
`timescale 1ns/1ps
`timescale 1ns/1ps


module  cmprs_afi_mux#(
module  cmprs_afi_mux#(
    parameter CMPRS_AFIMUX_ADDR=                'h140, //TODO: assign valid adderss
    parameter CMPRS_AFIMUX_MASK=                'h3f0,
    parameter CMPRS_AFIMUX_EN=                  'h0, // enables (gl;obal and per-channel)
    parameter CMPRS_AFIMUX_RST=                 'h1, // per-channel resets
    parameter CMPRS_AFIMUX_MODE=                'h2, // per-channel select - which register to return as status
    parameter CMPRS_AFIMUX_STATUS_CNTRL=        'h4, // .. 'h7
    parameter CMPRS_AFIMUX_SA_LEN=              'h8, // .. 'hf

    parameter CMPRS_AFIMUX_STATUS_REG_ADDR=     'h20,  //Uses 4 locations TODO: assign valid adderss
    parameter CMPRS_AFIMUX_WIDTH =              26, // maximal for status: currently only works with 26)
    parameter CMPRS_AFIMUX_CYCBITS =            3,
    parameter AFI_MUX_BUF_LATENCY =             2  // buffers read latency from fifo_ren* to fifo_rdata* valid : 2 if no register layers are used
    parameter AFI_MUX_BUF_LATENCY =             2  // buffers read latency from fifo_ren* to fifo_rdata* valid : 2 if no register layers are used
)(
)(
    input                         rst,
    input                         rst,
@@ -100,12 +111,33 @@ module cmprs_afi_mux#(
    output                        afi_wrissuecap1en
    output                        afi_wrissuecap1en
);
);
    reg         en;      // enable mux
    reg         en;      // enable mux
    reg         en_d;
    reg         en_d;    // or use it to reset all channels?
    reg   [3:0] en_chn;  // per-channel enable 
    reg   [3:0] en_chn;  // per-channel enable 
    
    
    wire [31:0] cmd_data;
    wire [31:0] cmd_data;
    wire [ 3:0] cmd_a;
    wire [ 3:0] cmd_a;
    wire        cmd_we_sa_len;    
    wire        cmd_we;
    wire        cmd_we_status_w;    
    wire        cmd_we_mode_w;    

    wire        cmd_we_sa_len_w;
    wire        cmd_we_en_w;    
    wire        cmd_we_rst_w; 

    reg [26:0] sa_len_d;
    reg  [2:0] sa_len_wa;
    reg  [3:0] rst_mclk;
    reg  [9:0] en_mclk;

    // hclk domain    
//    reg [26:0] sa_len_d;
//    reg  [2:0] sa_len_wa;
    wire       sa_len_we;
    wire       en_we;
    wire       en_rst;
    
    
       
    
    
//    reg   [2:0] cur_chn;          // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
//    reg   [2:0] cur_chn;          // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
    reg   [1:0] cur_chn;           // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
    reg   [1:0] cur_chn;           // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
@@ -138,7 +170,7 @@ module cmprs_afi_mux#(
    reg   [3:0] wleft; // number of 64-bit words left to be sent - also used as awlen (valid @ awvalid)
    reg   [3:0] wleft; // number of 64-bit words left to be sent - also used as awlen (valid @ awvalid)
    reg   [2:0] chunk_inc;              // how much to increment chunk pointer (1..4)
    reg   [2:0] chunk_inc;              // how much to increment chunk pointer (1..4)


    wire [ 3:0] reset_pointers;         // per-channel - after chunk_start_hclk or chunk_len_hclk were written or  explicit fifo_rst*
    reg [ 3:0] reset_pointers;         // per-channel - after chunk_start_hclk or chunk_len_hclk were written or  explicit fifo_rst*
    
    
    wire        ptr_resetting;          // pointers are being reset in cmprs_afi_mux_ptr module
    wire        ptr_resetting;          // pointers are being reset in cmprs_afi_mux_ptr module
    
    
@@ -157,6 +189,16 @@ module cmprs_afi_mux#(
    
    
    
    
    
    

    assign cmd_we_status_w = cmd_we && ((cmd_a & 'hc) ==       CMPRS_AFIMUX_STATUS_CNTRL);    
    assign cmd_we_mode_w =   cmd_we && (cmd_a ==               CMPRS_AFIMUX_MODE);    

    assign cmd_we_sa_len_w = cmd_we && ((cmd_a & 'h8) ==       CMPRS_AFIMUX_SA_LEN);
    assign cmd_we_en_w =     cmd_we && (cmd_a ==               CMPRS_AFIMUX_EN);    
    assign cmd_we_rst_w =    cmd_we && (cmd_a ==               CMPRS_AFIMUX_RST);    
    
    
    
    // use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout
    // use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout
    // compose ID of channel number, frame bumber LSBs and last/not last chunk
    // compose ID of channel number, frame bumber LSBs and last/not last chunk
    assign last_chunk_w[3:0] = {(left_to_eof[3]==1)?1'b1:1'b0,
    assign last_chunk_w[3:0] = {(left_to_eof[3]==1)?1'b1:1'b0,
@@ -186,6 +228,24 @@ module cmprs_afi_mux#(
    assign afi_wstrb =         8'hff;
    assign afi_wstrb =         8'hff;
    assign afi_wrissuecap1en = 1'b0;
    assign afi_wrissuecap1en = 1'b0;
    
    
    always @ (posedge mclk) begin
        if (cmd_we_sa_len_w) begin
            sa_len_d <= cmd_data[26:0];
            sa_len_wa <= cmd_a[2:0];
        end
        if (cmd_we_en_w)  en_mclk <=  cmd_data[9:0];
        if (cmd_we_rst_w) rst_mclk <= cmd_data[3:0];
    end

    always @ (posedge hclk) begin
        reset_pointers <= (en && !en_d)? 4'hf : (en_rst ? rst_mclk : 4'h0);
        if (en_we && en_mclk[1]) en_chn[0] <= en_mclk[0];
        if (en_we && en_mclk[3]) en_chn[1] <= en_mclk[2];
        if (en_we && en_mclk[5]) en_chn[2] <= en_mclk[4];
        if (en_we && en_mclk[7]) en_chn[3] <= en_mclk[6];
        if (en_we && en_mclk[9]) en <=        en_mclk[8];
    end

    
    
    always @ (posedge hclk) begin
    always @ (posedge hclk) begin
        en_d <= en;
        en_d <= en;
@@ -319,13 +379,30 @@ module cmprs_afi_mux#(
        .dout      ({wdata_en,wdata_sel}) // output[0:0] 
        .dout      ({wdata_en,wdata_sel}) // output[0:0] 
    );
    );
    
    
    cmd_deser #(
        .ADDR       (CMPRS_AFIMUX_ADDR),
        .ADDR_MASK  (CMPRS_AFIMUX_MASK),
        .NUM_CYCLES (6),
        .ADDR_WIDTH (4),
        .DATA_WIDTH (32)
    ) cmd_deser_32bit_i (
        .rst        (rst),      // input
        .clk        (mclk),     // input
        .ad         (cmd_ad),   // input[7:0] 
        .stb        (cmd_stb),  // input
        .addr       (cmd_a),    // output[3:0] 
        .data       (cmd_data), // output[31:0] 
        .we         (cmd_we)    // output
    );
    
    
    wire [26:0] chunk_ptr_rd01[0:1];
    wire [26:0] chunk_ptr_rd01[0:1];


    cmprs_afi_mux_ptr cmprs_afi_mux_ptr_i (
    cmprs_afi_mux_ptr cmprs_afi_mux_ptr_i (
        .hclk                (hclk),                // input
        .hclk                (hclk),                // input
        .sa_len_di           (cmd_data[26:0]),      // input[26:0] 
        .sa_len_di           (sa_len_d[26:0]),      // input[26:0] 
        .sa_len_wa           (cmd_a[2:0]),          // input[2:0] 
        .sa_len_wa           (sa_len_wa[2:0]),      // input[2:0] 
        .sa_len_we           (cmd_we_sa_len),       // input
        .sa_len_we           (sa_len_we),           // input
        .en                  (en),                  // input
        .en                  (en),                  // input
        .reset_pointers      (reset_pointers),      // input[3:0] 
        .reset_pointers      (reset_pointers),      // input[3:0] 
        .pre_busy_w          (pre_busy_w),          // input
        .pre_busy_w          (pre_busy_w),          // input
@@ -342,9 +419,9 @@ module cmprs_afi_mux#(
    assign chunk_ptr_rd=chunk_ptr_ra[3]?chunk_ptr_rd01[1]:chunk_ptr_rd01[0];
    assign chunk_ptr_rd=chunk_ptr_ra[3]?chunk_ptr_rd01[1]:chunk_ptr_rd01[0];
    cmprs_afi_mux_ptr_wresp cmprs_afi_mux_ptr_wresp_i (
    cmprs_afi_mux_ptr_wresp cmprs_afi_mux_ptr_wresp_i (
        .hclk                (hclk),                // input
        .hclk                (hclk),                // input
        .length_di           (cmd_data[26:0]),      // input[26:0] 
        .length_di           (sa_len_d[26:0]),      // input[26:0] 
        .length_wa           (cmd_a[1:0]),          // input[1:0] 
        .length_wa           (sa_len_wa[1:0]),      // input[1:0] 
        .length_we           (cmd_we_sa_len & cmd_a[2]), // input
        .length_we           (sa_len_we & sa_len_wa[2]), // input
        .en                  (en),                  // input
        .en                  (en),                  // input
        .reset_pointers      (reset_pointers),      // input[3:0] 
        .reset_pointers      (reset_pointers),      // input[3:0] 
        .chunk_ptr_ra        (chunk_ptr_ra[2:0]),   // input[2:0] 
        .chunk_ptr_ra        (chunk_ptr_ra[2:0]),   // input[2:0] 
@@ -355,6 +432,28 @@ module cmprs_afi_mux#(
        .afi_bid             (afi_bid)              // input[5:0] 
        .afi_bid             (afi_bid)              // input[5:0] 
    );
    );


    /* Instance template for module cmprs_afi_mux_status */
    cmprs_afi_mux_status #(
        .CMPRS_AFIMUX_STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR),
        .CMPRS_AFIMUX_WIDTH(CMPRS_AFIMUX_WIDTH),
        .CMPRS_AFIMUX_CYCBITS(CMPRS_AFIMUX_CYCBITS)
    ) cmprs_afi_mux_status_i (
        .rst          (rst), // input
        .hclk         (hclk), // input
        .mclk         (mclk), // input
        .cmd_data     (cmd_data[15:0]), // input[15:0] 
        .cmd_a        (cmd_a[1:0]), // input[1:0] 
        .status_we    (cmd_we_status_w), // input
        .mode_we      (cmd_we_mode_w), // input
        .status_ad    (status_ad), // output[7:0] 
        .status_rq    (status_rq), // output
        .status_start (status_start), // input
        .en           (en), // input
        .chunk_ptr_ra (chunk_ptr_ra), // output[3:0] reg 
        .chunk_ptr_rd (chunk_ptr_rd[CMPRS_AFIMUX_WIDTH-1:0]) // input[25:0] 
    );
    pulse_cross_clock sa_len_we_i (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_sa_len_w), .out_pulse(sa_len_we),.busy());
    pulse_cross_clock en_we_i     (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_en_w),     .out_pulse(en_we),    .busy());
    pulse_cross_clock en_rst_i    (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_rst_w),    .out_pulse(en_rst),.busy());


endmodule
endmodule
+184 −0
Original line number Original line Diff line number Diff line
/*******************************************************************************
 * Module: cmprs_afi_mux_status
 * Date:2015-06-28  
 * Author: andrey     
 * Description: prepare and send per-channel chunk pointer information as status
 * Using 4 consecutive locations. Each channel can provide one of the 4 pointers:
 * frame pointer in the write channel, current chunk pointer in the write channel
 * and the same for the write response channel (confirmed written to the system
 * memory
 *
 * Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
 * cmprs_afi_mux_status.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_afi_mux_status.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_afi_mux_status #(
    parameter CMPRS_AFIMUX_STATUS_REG_ADDR=     'h20,  //Uses 4 locations TODO: assign valid adderss
    parameter CMPRS_AFIMUX_WIDTH =              26, // maximal for status: currently only works with 26)
    parameter CMPRS_AFIMUX_CYCBITS =            3
 ) (
    input                          rst,
    input                          hclk,         // global clock to run axi_hp @ 150MHz, shared by all compressor channels
    input                          mclk,         // for command/status
    // mclk domain
    input                   [15:0] cmd_data,     //  
    input                   [ 1:0] cmd_a,        //
    input                          status_we,    //
    input                          mode_we,      //
      
    output                   [7:0] status_ad,    // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
    output                         status_rq,    // input request to send status downstream
    input                          status_start, // Acknowledge of the first status packet byte (address)
    // hclk domain
    input                          en,           // 1- enable, 0 - reset
    output reg               [3:0] chunk_ptr_ra, // full pointer address - {eof,wresp,chn[1:0]}
    input [CMPRS_AFIMUX_WIDTH-1:0] chunk_ptr_rd  // pointer data
);
    reg [15:0] mode_data_mclk; // some bits unused
    wire       mode_we_hclk;
    reg  [7:0] mode_hclk;
//    wire [1:0] sel[0:3]={mode_hclk[7:6],mode_hclk[5:4],mode_hclk[3:2],mode_hclk[1:0]};

    reg  [1:0] index;
    reg  [CMPRS_AFIMUX_CYCBITS-1:0] cntr;
    reg    [CMPRS_AFIMUX_WIDTH-1:0] chunk_ptr_hclk;  // pointer data
    reg                       [1:0] chunk_chn_hclk;  // pointer channel
    
    reg    [CMPRS_AFIMUX_WIDTH-1:0] status_data[0:3];
    
    wire stb_w;
    reg  stb_r;
    wire stb_mclk;
    
    wire [7:0] ad[0:3];
    wire [3:0] rq;
    wire [3:0] start;
    
    assign stb_w = en && (cntr==0);
    always @ (posedge mclk) begin
        if (mode_we) mode_data_mclk <= cmd_data[15:0];
    end

    always @ (posedge hclk) begin
        if (mode_we_hclk) begin 
            if (mode_data_mclk[ 2]) mode_hclk[1:0] <= mode_data_mclk[ 1: 0];
            if (mode_data_mclk[ 6]) mode_hclk[3:2] <= mode_data_mclk[ 5: 4];
            if (mode_data_mclk[10]) mode_hclk[5:4] <= mode_data_mclk[ 9: 8];
            if (mode_data_mclk[14]) mode_hclk[7:6] <= mode_data_mclk[13:12];
            
            if (stb_mclk) status_data[chunk_chn_hclk] <= chunk_ptr_hclk;
        end
        
        if (!en) {index,cntr} <= 0;
        else     {index,cntr} <= {index,cntr} + 1;
        
        if (stb_w) begin
            chunk_ptr_ra[1:0] <= index;
            case (index) 
                2'h0: chunk_ptr_ra[3:2] <= mode_hclk[1:0] ^ 1; // so 0 will be eof, internal
                2'h1: chunk_ptr_ra[3:2] <= mode_hclk[3:2] ^ 1;
                2'h2: chunk_ptr_ra[3:2] <= mode_hclk[5:4] ^ 1;
                2'h3: chunk_ptr_ra[3:2] <= mode_hclk[7:6] ^ 1;
            endcase
        end
        stb_r <= stb_w;
        if (stb_r) begin
            chunk_ptr_hclk <= {chunk_ptr_rd[23:0],chunk_ptr_rd[25:24]}; // bits 0,1 are sent to 25:24
            chunk_chn_hclk <= index;
        end
        
    end
    
    pulse_cross_clock mode_we_hclk_i (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(mode_we), .out_pulse(mode_we_hclk),.busy());
    pulse_cross_clock stb_mclk_i     (.rst(rst), .src_clk(hclk), .dst_clk(mclk), .in_pulse(stb_r),   .out_pulse(stb_mclk),    .busy());
    status_router4 status_router4_i (
        .rst       (rst),          // input
        .clk       (mclk),         // input
        .db_in0    (ad[0]),        // input[7:0] 
        .rq_in0    (rq[0]),        // input
        .start_in0 (start[0]),     // output

        .db_in1    (ad[1]),        // input[7:0] 
        .rq_in1    (rq[1]),        // input
        .start_in1 (start[1]),     // output
        .db_in2    (ad[2]),        // input[7:0] 
        .rq_in2    (rq[2]),        // input
        .start_in2 (start[2]),     // output
        .db_in3    (ad[3]),        // input[7:0] 
        .rq_in3    (rq[3]),        // input
        .start_in3 (start[3]),     // output
        .db_out    (status_ad),    // output[7:0] 
        .rq_out    (status_rq),    // output
        .start_out (status_start)  // input
    );

    status_generate #(
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate0_i (
        .rst     (rst),                     // input
        .clk     (mclk),                    // input
        .we      (status_we && (cmd_a==0)), // input
        .wd      (cmd_data[7:0]),           // input[7:0] 
        .status  (status_data[0]),          // input[25:0] 
        .ad      (ad[0]),                   // output[7:0] 
        .rq      (rq[0]),                   // output
        .start   (start[0])                 // input
    );

    status_generate #(
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate1_i (
        .rst     (rst),                     // input
        .clk     (mclk),                    // input
        .we      (status_we && (cmd_a==1)), // input
        .wd      (cmd_data[7:0]),           // input[7:0] 
        .status  (status_data[1]),          // input[25:0] 
        .ad      (ad[1]),                   // output[7:0] 
        .rq      (rq[1]),                   // output
        .start   (start[1])                 // input
    );

    status_generate #(
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate2_i (
        .rst     (rst),                     // input
        .clk     (mclk),                    // input
        .we      (status_we && (cmd_a==2)), // input
        .wd      (cmd_data[7:0]),           // input[7:0] 
        .status  (status_data[2]),          // input[25:0] 
        .ad      (ad[2]),                   // output[7:0] 
        .rq      (rq[2]),                   // output
        .start   (start[2])                 // input
    );

    status_generate #(
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate3_i (
        .rst     (rst),                     // input
        .clk     (mclk),                    // input
        .we      (status_we && (cmd_a==3)), // input
        .wd      (cmd_data[7:0]),           // input[7:0] 
        .status  (status_data[3]),          // input[25:0] 
        .ad      (ad[3]),                   // output[7:0] 
        .rq      (rq[3]),                   // output
        .start   (start[3])                 // input
    );

endmodule