cmprs_afi_mux_status.v 11.1 KB
Newer Older
1 2 3
/*******************************************************************************
 * Module: cmprs_afi_mux_status
 * Date:2015-06-28  
4
 * Author: Andrey Filippov     
5 6 7 8 9 10
 * 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
 *
11
 * Copyright (c) 2015 Elphel, Inc.
12 13 14 15 16 17 18 19 20 21 22 23
 * 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/> .
24 25 26 27 28 29
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
30
 * files and/or simulating the code, the copyright holders of this Program give
31 32
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
33
 * charge, and there is no dependence on any encrypted modules for simulating of
34 35 36
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
37 38 39 40
 *******************************************************************************/
`timescale 1ns/1ps

module  cmprs_afi_mux_status #(
41
    parameter CMPRS_AFIMUX_STATUS_REG_ADDR=     'h20,  //Uses 4 locations TODO: assign valid address
42 43 44
    parameter CMPRS_AFIMUX_WIDTH =              26, // maximal for status: currently only works with 26)
    parameter CMPRS_AFIMUX_CYCBITS =            3
 ) (
Andrey Filippov's avatar
Andrey Filippov committed
45
//    input                          rst,
46 47
    input                          hclk,         // global clock to run axi_hp @ 150MHz, shared by all compressor channels
    input                          mclk,         // for command/status
Andrey Filippov's avatar
Andrey Filippov committed
48 49
    input                          mrst,      // @posedge mclk, sync reset
    input                          hrst,      // @posedge xclk, sync reset
50 51 52 53 54 55 56 57 58 59 60 61 62 63
    // 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
);
64
   localparam MODE_WIDTH = 15;
65
    reg             [MODE_WIDTH-1:0] mode_data_mclk; // some bits unused
Andrey Filippov's avatar
Andrey Filippov committed
66 67 68
    wire                             mode_we_hclk;
    reg                        [7:0] mode_hclk;
    reg                        [1:0] index;
69 70 71
    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
72
    
73
    reg [4 * CMPRS_AFIMUX_WIDTH-1:0] status_data;
74 75 76 77 78
    
    wire stb_w;
    reg  stb_r;
    wire stb_mclk;
    
79 80 81
    wire [31:0] ad;
    wire  [3:0] rq;
    wire  [3:0] start;
82 83 84
    
    assign stb_w = en && (cntr==0);
    always @ (posedge mclk) begin
85
        if (mode_we) mode_data_mclk <= cmd_data[MODE_WIDTH-1:0];
86 87 88 89 90 91 92 93 94
    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];
        end
95 96 97 98 99 100
            
       if (stb_mclk) status_data[chunk_chn_hclk * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
//       if (stb_mclk && (chunk_chn_hclk == 2'h0)) status_data[0 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
//       if (stb_mclk && (chunk_chn_hclk == 2'h1)) status_data[1 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
//       if (stb_mclk && (chunk_chn_hclk == 2'h2)) status_data[2 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
//       if (stb_mclk && (chunk_chn_hclk == 2'h3)) status_data[3 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH] <= chunk_ptr_hclk;
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
        
        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
    
Andrey Filippov's avatar
Andrey Filippov committed
122 123
    pulse_cross_clock mode_we_hclk_i (.rst(mrst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(mode_we), .out_pulse(mode_we_hclk),.busy());
    pulse_cross_clock stb_mclk_i     (.rst(hrst), .src_clk(hclk), .dst_clk(mclk), .in_pulse(stb_r),   .out_pulse(stb_mclk),    .busy());
124
    status_router4 status_router4_i (
Andrey Filippov's avatar
Andrey Filippov committed
125
        .rst       (1'b0), // rst),            // input
126
        .clk       (mclk),           // input
Andrey Filippov's avatar
Andrey Filippov committed
127
        .srst      (mrst),            // input
128 129 130
        .db_in0    (ad[0 * 8 +: 8]), // input[7:0] 
        .rq_in0    (rq[0]),          // input
        .start_in0 (start[0]),       // output
131

132 133 134 135 136 137 138 139 140 141 142 143
        .db_in1    (ad[1 * 8 +: 8]), // input[7:0] 
        .rq_in1    (rq[1]),          // input
        .start_in1 (start[1]),       // output
        .db_in2    (ad[2 * 8 +: 8]), // input[7:0] 
        .rq_in2    (rq[2]),          // input
        .start_in2 (start[2]),       // output
        .db_in3    (ad[3 * 8 +: 8]), // 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
144 145 146 147 148 149
    );

    status_generate #(
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate0_i (
Andrey Filippov's avatar
Andrey Filippov committed
150
        .rst     (1'b0),             //rst),                                                       // input
151
        .clk     (mclk),                                                      // input
Andrey Filippov's avatar
Andrey Filippov committed
152
        .srst    (mrst),                                                      // input
153 154 155 156 157 158
        .we      (status_we && (cmd_a==0)),                                   // input
        .wd      (cmd_data[7:0]),                                             // input[7:0] 
        .status  (status_data[0 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0] 
        .ad      (ad[0 * 8 +: 8]),                                            // output[7:0] 
        .rq      (rq[0]),                                                     // output
        .start   (start[0])                                                   // input
159 160 161
    );

    status_generate #(
162
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+1),
163 164
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate1_i (
Andrey Filippov's avatar
Andrey Filippov committed
165
        .rst     (1'b0), //rst),                                                       // input
166
        .clk     (mclk),                                                      // input
Andrey Filippov's avatar
Andrey Filippov committed
167
        .srst    (mrst),                                                      // input
168 169 170 171 172 173
        .we      (status_we && (cmd_a==1)),                                   // input
        .wd      (cmd_data[7:0]),                                             // input[7:0] 
        .status  (status_data[1 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0] 
        .ad      (ad[1 * 8 +: 8]),                                            // output[7:0] 
        .rq      (rq[1]),                                                     // output
        .start   (start[1])                                                   // input
174 175 176
    );

    status_generate #(
177
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+2),
178 179
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate2_i (
Andrey Filippov's avatar
Andrey Filippov committed
180
        .rst     (1'b0), //rst),                                                       // input
181
        .clk     (mclk),                                                      // input
Andrey Filippov's avatar
Andrey Filippov committed
182
        .srst    (mrst),                                                      // input
183 184 185 186 187 188
        .we      (status_we && (cmd_a==2)),                                   // input
        .wd      (cmd_data[7:0]),                                             // input[7:0] 
        .status  (status_data[2 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0] 
        .ad      (ad[2 * 8 +: 8]),                                            // output[7:0] 
        .rq      (rq[2]),                                                     // output
        .start   (start[2])                                                   // input
189 190 191
    );

    status_generate #(
192
        .STATUS_REG_ADDR  (CMPRS_AFIMUX_STATUS_REG_ADDR+3),
193 194
        .PAYLOAD_BITS     (CMPRS_AFIMUX_WIDTH)
    ) status_generate3_i (
Andrey Filippov's avatar
Andrey Filippov committed
195
        .rst     (1'b0), // rst),                                                       // input
196
        .clk     (mclk),                                                      // input
Andrey Filippov's avatar
Andrey Filippov committed
197
        .srst    (mrst),                                                      // input
198 199 200 201 202 203
        .we      (status_we && (cmd_a==3)),                                   // input
        .wd      (cmd_data[7:0]),                                             // input[7:0] 
        .status  (status_data[3 * CMPRS_AFIMUX_WIDTH +: CMPRS_AFIMUX_WIDTH]), // input[25:0] 
        .ad      (ad[3 * 8 +: 8]),                                            // output[7:0] 
        .rq      (rq[3]),                                                     // output
        .start   (start[3])                                                   // input
204 205 206 207
    );

endmodule