cmd_readback.v 4.69 KB
Newer Older
1 2 3
/*******************************************************************************
 * Module: cmd_readback
 * Date:2015-05-05  
4
 * Author: Andrey Filippov     
5 6
 * Description: Store control register data and readback
 *
7
 * Copyright (c) 2015 Elphel, Inc.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * 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/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  cmd_readback#(
    parameter AXI_WR_ADDR_BITS=              14,
    parameter AXI_RD_ADDR_BITS =             14,
26
    parameter CONTROL_RBACK_DEPTH=           11, // 10 - 1xbram, 11 - 2xbram
27
    
28 29 30 31
    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
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 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 93 94 95 96 97 98 99 100 101 102 103 104
)(
    input                            rst,
    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; 
    
    
    always @ (posedge rst or posedge axi_clk) begin
        if (rst) axird_regen <= 0;
        else    axird_regen <= axird_ren;
        
        if      (rst)               select_r <= 0;
        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
    
    always @ (posedge rst or posedge mclk) begin
        if (rst) we <= 0;
        else     we <= we_w;
    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