cmd_readback.v 5.57 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*!
 * <b>Module:</b>cmd_readback
 * @file cmd_readback.v
 * @date 2015-05-05  
 * @author Andrey Filippov     
 *
 * @brief Store control register data and readback
 *
 * @copyright Copyright (c) 2015 Elphel, Inc.
 *
 * <b>License:</b>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * cmd_readback.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.
 *
 *  cmd_readback.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/> .
25 26 27 28 29 30
 *
 * 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"
31
 * files and/or simulating the code, the copyright holders of this Program give
32 33
 * 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
34
 * charge, and there is no dependence on any encrypted modules for simulating of
35 36 37
 * 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.
38
 */
39 40 41 42 43
`timescale 1ns/1ps

module  cmd_readback#(
    parameter AXI_WR_ADDR_BITS=              14,
    parameter AXI_RD_ADDR_BITS =             14,
44
    parameter CONTROL_RBACK_DEPTH=           11, // 10 - 1xbram, 11 - 2xbram
45
    
46 47 48 49
    parameter CONTROL_ADDR =             'h0000,  // AXI write address of control write registers
    parameter CONTROL_ADDR_MASK =        'h3800,  // AXI write address of control registers
    parameter CONTROL_RBACK_ADDR =       'h0000,  // AXI write address of control write registers
    parameter CONTROL_RBACK_ADDR_MASK =  'h3800   // AXI write address of control registers
50
)(
Andrey Filippov's avatar
Andrey Filippov committed
51 52
    input                            mrst, // @posedge mclk - sync reset
    input                            arst, // @posedge axi_clk - sync reset
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    input                            mclk,
    input                            axi_clk,
    input     [AXI_WR_ADDR_BITS-1:0] par_waddr,     // parallel address
    input                     [31:0] par_data,      // parallel 32-bit data
    input                            ad_stb,        // low address output strobe (and parallel A/D)
    
    input    [AXI_RD_ADDR_BITS-1:0] axird_pre_araddr,  // status read address, 1 cycle ahead of read data
    input                           axird_start_burst, // start of read burst, valid pre_araddr, save externally to control ext. dev_ready multiplexer
    input [CONTROL_RBACK_DEPTH-1:0] axird_raddr,       //   .raddr(read_in_progress?read_address[9:0]:10'h3ff),    // read address
    input                           axird_ren,         //      .ren(bram_reg_re_w) ,      // read port enable
//    input                        axird_regen,       //==axird_ren?? - remove?   .regen(bram_reg_re_w),        // output register enable
    output                 [31:0]   axird_rdata,       // combinatorial multiplexed (add external register layer, modify axibram_read?)     .data_out(rdata[31:0]),       // data out
    output                          axird_selected    // axird_rdata contains cvalid data from this module, vcalid next after axird_start_burst

);
    localparam integer DATA_2DEPTH = (1<<CONTROL_RBACK_DEPTH)-1;
    reg  [31:0] ram [0:DATA_2DEPTH];
    reg  [CONTROL_RBACK_DEPTH-1:0] waddr;
    reg                            we;
    reg                    [31: 0] wdata;
    
    wire                           select_w;
    reg                            select_r;
    reg                            select_d;
    
    wire                           rd;
    wire                           regen;
    reg                   [31:0]   axi_rback_rdata; 
    reg                   [31:0]   axi_rback_rdata_r;
    reg                            axird_regen;
    wire                           we_w;
    
    assign we_w = ad_stb && (((par_waddr ^ CONTROL_ADDR) & CONTROL_ADDR_MASK)==0);
    assign select_w = ((axird_pre_araddr ^ CONTROL_RBACK_ADDR) & CONTROL_RBACK_ADDR_MASK)==0;
    assign rd =        axird_ren   && select_r;
    assign regen =     axird_regen && select_d;
    assign axird_rdata=axi_rback_rdata_r;
    assign axird_selected = select_r; 
    
    
Andrey Filippov's avatar
Andrey Filippov committed
93 94 95
    always @ (posedge axi_clk) begin
        if (arst) axird_regen <= 0;
        else      axird_regen <= axird_ren;
96
        
Andrey Filippov's avatar
Andrey Filippov committed
97
        if      (arst)              select_r <= 0;
98 99 100 101 102 103 104 105 106
        else if (axird_start_burst) select_r <= select_w;
    
    end
    always @ (posedge axi_clk) begin
        if (rd)       axi_rback_rdata <= ram[axird_raddr];
        if (regen)    axi_rback_rdata_r <= axi_rback_rdata;
        select_d <=   select_r;
    end
    
Andrey Filippov's avatar
Andrey Filippov committed
107 108 109
    always @ (posedge mclk) begin
        if (mrst) we <= 0;
        else      we <= we_w;
110 111 112 113 114 115 116 117 118 119 120 121 122 123
    end
    always @ (posedge mclk) begin
        if (we_w) wdata <= par_data;
        if (we_w) waddr <= par_waddr[CONTROL_RBACK_DEPTH-1:0];
        
    end

    always @ (posedge mclk) begin
        if (we)     ram[waddr]  <= wdata; // shifted data here
    end
    

endmodule