status_read.v 6.19 KB
Newer Older
1 2 3
/*******************************************************************************
 * Module: status_read
 * Date:2015-01-14  
4
 * Author: Andrey Filippov     
5 6 7 8 9 10 11 12 13 14
 * Description: Receives status read data (low bandwidth) from multiple
 * subsystems byte-serial, stores in axi-addressable memory
 * 8-bita ddress is received from the source module,
 * as well as another (optional) byte of sequence number (set in write command)
 * Sequence number (received first afther the address) is stored as a high byte,
 * lower bytes are the actual payload, starting from lower byte (not all 3 are
 * required. Single-bit responsen can be combined in the same byte with the
 * sequence number to use just 2-byte packets? 
 * TODO: add interrupt capabilities
 *
15
 * Copyright (c) 2015 Elphel, Inc.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 * status_read.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.
 *
 *  status_read.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  status_read#(
32
    parameter STATUS_ADDR =           'h0800, // AXI read address of status read registers
33 34
    parameter STATUS_ADDR_MASK =      'h3c00, // AXI write address of status registers
    parameter AXI_RD_ADDR_BITS =      14,
35
    parameter integer STATUS_DEPTH=   8 // 256 cells, maybe just 16..64 are enough?
36
)(
Andrey Filippov's avatar
Andrey Filippov committed
37 38 39
    input                        mrst, // @posedge mclk - sync reset
    input                        arst, // @posedge axi_clk - sync reset
    input                        clk,
40 41 42 43 44 45 46 47 48
    input                        axi_clk,   // common for read and write channels
    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     [STATUS_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
                                                 // so with ren/regen it may be delayed 1 more cycle
49 50 51 52
    input                  [7:0] ad,               // byte-serial status data from the sources
    input                        rq,               // request from sources to transfer status data
    output                       start             // acknowledge receiving of first byte (address), currently always ready
);
53
    localparam integer DATA_2DEPTH=(1<<STATUS_DEPTH)-1;
54
    reg  [31:0] ram [0:DATA_2DEPTH];
55
    reg         [STATUS_DEPTH-1:0] waddr;
56 57 58 59 60
    reg                          we;
    reg                  [31: 0] wdata;
    reg                          rq_r;
    reg                   [3:0]  dstb;
    
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    wire                         select_w;
    reg                          select_r;
    reg                          select_d;
    
    wire                         rd;
    wire                         regen;
    reg                 [31:0]   axi_status_rdata; 
    reg                 [31:0]   axi_status_rdata_r;
    
    assign select_w = ((axird_pre_araddr ^ STATUS_ADDR) & STATUS_ADDR_MASK)==0;
    assign rd =        axird_ren   && select_r;
    assign regen =     axird_regen && select_d;
    
    
    
    
//    assign re= pre_stb && (((axi_pre_addr ^ STATUS_ADDR) & STATUS_ADDR_MASK) == 0);
//    assign raddr=axi_pre_addr[STATUS_DEPTH-1:0];
79
    assign start=rq && !rq_r;
80 81
    assign axird_rdata=axi_status_rdata_r;
    assign axird_selected = select_r; 
Andrey Filippov's avatar
Andrey Filippov committed
82 83
    always @ (posedge axi_clk) begin
        if      (arst)              select_r <= 0;
84 85 86 87 88 89 90 91
        else if (axird_start_burst) select_r <= select_w;
    end
    always @ (posedge axi_clk) begin
        if (rd)       axi_status_rdata <= ram[axird_raddr];
        if (regen)    axi_status_rdata_r <= axi_status_rdata;
        
        select_d <=   select_r;
    end
92
    
Andrey Filippov's avatar
Andrey Filippov committed
93
    always @ (posedge clk) begin
94
        
Andrey Filippov's avatar
Andrey Filippov committed
95 96
        if (mrst) rq_r <= 0;
        else      rq_r <= rq;
97
        
Andrey Filippov's avatar
Andrey Filippov committed
98
        if (mrst)       dstb <= 0;
99 100 101
        else if (!rq)   dstb <= 0;
        else            dstb <= {dstb[2:0],~rq_r};
        // byte 0 - address
Andrey Filippov's avatar
Andrey Filippov committed
102
        if (mrst)       waddr <= 0;
103
        else if (start) waddr <= ad[STATUS_DEPTH-1:0];
104 105 106 107
        
        // byte 1 - 2 payload bits and sequence number
        // 6 bits of the sequence number will go to bits 26.. 31
        // 2 bits (24,25) are payload status
Andrey Filippov's avatar
Andrey Filippov committed
108
        if (mrst)         wdata[31:24] <= 0;
109 110 111 112
        else if (start)   wdata[31:24] <= 0;
        else if (dstb[0]) wdata[31:24] <= ad;

        // byte 2 - payload bits 0..7 
Andrey Filippov's avatar
Andrey Filippov committed
113
        if (mrst)         wdata[ 7: 0] <= 0;
114 115 116 117
        else if (start)   wdata[ 7: 0] <= 0;
        else if (dstb[1]) wdata[ 7: 0] <= ad;
        
        // byte 3 - payload bits 8..15 
Andrey Filippov's avatar
Andrey Filippov committed
118
        if (mrst)         wdata[15: 8] <= 0;
119 120 121 122
        else if (start)   wdata[15: 8] <= 0;
        else if (dstb[2]) wdata[15: 8] <= ad;

        // byte 4 - payload bits 16..23 
Andrey Filippov's avatar
Andrey Filippov committed
123
        if (mrst)         wdata[23:16] <= 0;
124 125 126
        else if (start)   wdata[23:16] <= 0;
        else if (dstb[3]) wdata[23:16] <= ad;
        
Andrey Filippov's avatar
Andrey Filippov committed
127
        if (mrst)         we <= 0;
128 129 130 131
        else              we <= !rq && rq_r; 
    end
    
    always @ (posedge clk) begin
132
        if (we)     ram[waddr]  <= wdata; // shifted data here
133 134 135 136 137 138
    end
                             


endmodule