axibram_read.v 12.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*******************************************************************************
 * Module: axibram_read
 * Date:2014-03-18  
 * Author: Andrey Filippov
 * Description: Read block RAM memory over AXI PS Master GP0
 *
 * Copyright (c) 2014 Elphel, Inc.
 * axibram_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.
 *
 *  axibram_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/> .
 *******************************************************************************/
21
 // Check that this fix did not break anything:
22
`include "system_defines.vh" 
23
`define USE_SHORT_REN_REGEN 
24
module  axibram_read #(
25 26 27
    parameter ADDRESS_BITS = 10 // number of memory address bits
)(
   input         aclk,    // clock - should be buffered
28 29
//   input         aresetn, // reset, active low
   input         rst, // reset, active high
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
// AXI Read Address   
   input  [31:0] araddr,  // ARADDR[31:0], input 
   input         arvalid, // ARVALID, input
   output        arready, // ARREADY, output
   input  [11:0] arid,    // ARID[11:0], input
//   input  [ 1:0] arlock,  // ARLOCK[1:0], input
//   input  [ 3:0] archache,// ARCACHE[3:0], input
//   input  [ 2:0] arprot,  // ARPROT[2:0], input
   input  [ 3:0] arlen,   // ARLEN[3:0], input
   input  [ 1:0] arsize,  // ARSIZE[1:0], input
   input  [ 1:0] arburst, // ARBURST[1:0], input
//   input  [ 3:0] adqos,   // ARQOS[3:0], input
// AXI Read Data
   output [31:0] rdata,   // RDATA[31:0], output
   output reg    rvalid,  // RVALID, output
   input         rready,  // RREADY, input
   output reg [11:0] rid,     // RID[11:0], output
   output reg    rlast,   // RLAST, output
   output [ 1:0] rresp,
49 50 51 52 53 54
// External memory synchronization
   output [ADDRESS_BITS-1:0] pre_araddr, // same as awaddr_out, early address to decode and return dev_ready
   output        start_burst, // start of read burst, valid pre_araddr, save externally to control ext. dev_ready multiplexer
   input         dev_ready,   // extrernal combinatorial ready signal, multiplexed from different sources according to pre_araddr@start_burst
   
// External memory interface   
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
   output        bram_rclk,  //      .rclk(aclk),                  // clock for read port
   output  [ADDRESS_BITS-1:0] bram_raddr, //   .raddr(read_in_progress?read_address[9:0]:10'h3ff),    // read address
   output        bram_ren,   //      .ren(bram_reg_re_w) ,      // read port enable
   output        bram_regen, //   .regen(bram_reg_re_w),        // output register enable
   input  [31:0] bram_rdata  //      .data_out(rdata[31:0]),       // data out
      // RRESP[1:0], output
);
// **** AXI Read channel ****
    wire ar_nempty;
    wire ar_half_full;
    assign arready=~ar_half_full;
    wire [ 1:0] arburst_out;
    // SuppressWarnings VEditor all 
    wire [ 1:0] arsize_out; // not used 
    wire [ 3:0] arlen_out;
    wire [ADDRESS_BITS-1:0] araddr_out;
    wire [11:0] arid_out;
72
//    wire rst=~aresetn;
73 74 75 76 77 78 79 80 81 82
    reg  read_in_progress=0;
    reg  read_in_progress_d=0; // delayed by one active cycle (not skipped)
    reg  read_in_progress_or=0; // read_in_progress || read_in_progress_d
    
    reg  [ADDRESS_BITS-1:0] read_address;       // transfer address (not including lower bits 
    reg  [ 3:0] read_left;          // number of read transfers
// will ignore arsize - assuming always 32 bits  (a*size[2:0]==2)
    reg  [ 1:0] rburst;             // registered burst type 
    reg  [ 3:0] rlen;               // registered burst type 
    wire [ADDRESS_BITS-1:0] next_rd_address_w;     // next transfer address;
83
    assign      next_rd_address_w= //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 13-bit target.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
      rburst[1]?
        (rburst[0]? {ADDRESS_BITS{1'b0}}:((read_address[ADDRESS_BITS-1:0]+1) & {{(ADDRESS_BITS-4){1'b1}}, ~rlen[3:0]})):
        (rburst[0]? (read_address[ADDRESS_BITS-1:0]+1):(read_address[ADDRESS_BITS-1:0]));
    wire start_read_burst_w;
//    wire bram_re_w;
    wire bram_reg_re_w;
    wire read_in_progress_w;
    wire read_in_progress_d_w;
    wire last_in_burst_w;
    wire last_in_burst_d_w;
    reg  pre_last_in_burst_r;
    assign rresp=2'b0;
    // reduce combinatorial delay from rready (use it in final mux)
//    assign bram_reg_re_w=     read_in_progress && (!rvalid || rready);
//    assign start_read_burst_w=ar_nempty && (!read_in_progress || (bram_reg_re_w && (read_left==4'b0))); // reduce delay from arready
    assign last_in_burst_w=  bram_reg_re_w && (read_left==4'b0);
    assign last_in_burst_d_w=bram_reg_re_w && pre_last_in_burst_r;
    // make sure ar_nempty is updated
//    assign start_read_burst_w=ar_nempty && (!read_in_progress || last_in_burst_w); // reduce delay from arready
    assign read_in_progress_w=  start_read_burst_w || (read_in_progress && !last_in_burst_w); // reduce delay from arready
    
    assign read_in_progress_d_w=(read_in_progress && bram_reg_re_w) ||
     (read_in_progress && !last_in_burst_d_w); // reduce delay from arready

//    assign read_in_progress_d_w=read_in_progress_d;

    wire pre_rvalid_w;
    assign  pre_rvalid_w=bram_reg_re_w || (rvalid && !rready);
    
    wire pre_left_zero_w;
114 115 116 117
    // TODO: Speed up by moving registers
    // SuppressWarnings VEditor all - not yet used 
    reg bram_reg_re_0;
    // SuppressWarnings VEditor all - not yet used 
118
    reg last_in_burst_1;
119
    // SuppressWarnings VEditor all - not yet used 
120
    reg last_in_burst_0;
121
    // SuppressWarnings VEditor all - not yet used 
122
    reg start_read_burst_0;
123
    // SuppressWarnings VEditor all - not yet used 
124 125 126
    reg start_read_burst_1;
    reg [11:0] pre_rid0;
    reg [11:0] pre_rid;
127
    
128 129 130 131 132
// External memory interface - synchronization with ready
   assign pre_araddr=  araddr_out[ADDRESS_BITS-1:0];
   assign start_burst= start_read_burst_w;
   //input dev_ready,   // extrernal combinatorial ready signal, multiplexed from different sources according to pre_araddr@start_burst 
// External memory interface
133 134
   assign  bram_rclk =  aclk;  // clock for read port
   assign  bram_raddr = read_in_progress?read_address[ADDRESS_BITS-1:0]:{ADDRESS_BITS{1'b1}};  // read address
135 136 137
   
`ifdef USE_SHORT_REN_REGEN   
   reg bram_regen_r;
Andrey Filippov's avatar
Andrey Filippov committed
138 139
//   assign  bram_ren =   bram_reg_re_w && !pre_last_in_burst_r ;     // read port enable
   assign  bram_ren = read_in_progress;
140 141
   assign  bram_regen = bram_regen_r;     // output register enable
`else
142 143
   assign  bram_ren =   bram_reg_re_w;     // read port enable
   assign  bram_regen = bram_reg_re_w;     // output register enable
144
`endif   
145
   
146 147 148
   assign  rdata[31:0] = bram_rdata;    // data out

    always @ (posedge  aclk or posedge  rst) begin
149 150 151 152 153
`ifdef USE_SHORT_REN_REGEN   
      if   (rst)  bram_regen_r <= 0;
      else        bram_regen_r <=  bram_ren;
`endif    
   
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
      if   (rst)                   pre_last_in_burst_r <= 0;
//      else if (start_read_burst_w) pre_last_in_burst_r <= (read_left==4'b0);
      else if (bram_reg_re_w)      pre_last_in_burst_r <= (read_left==4'b0);
    
      if   (rst)                   rburst[1:0] <= 0;
      else if (start_read_burst_w) rburst[1:0] <= arburst_out[1:0];

      if   (rst)                   rlen[3:0] <= 0;
      else if (start_read_burst_w) rlen[3:0] <= arlen_out[3:0];
    
      if   (rst) read_in_progress <= 0;
      else       read_in_progress <= read_in_progress_w;

      if   (rst)                read_in_progress_d <= 0;
//      else   read_in_progress_d <= read_in_progress_d_w;
      else if (bram_reg_re_w)   read_in_progress_d <= read_in_progress_d_w;
      
      if   (rst) read_in_progress_or <= 0;
//      else       read_in_progress_or <= read_in_progress_d_w || read_in_progress_w;
//      else  if (bram_reg_re_w) read_in_progress_or <= read_in_progress_d_w || read_in_progress_w;
// FIXME:
      else  if (bram_reg_re_w || !read_in_progress_or) read_in_progress_or <= read_in_progress_d_w || read_in_progress_w;
      
//    reg  read_in_progress_d=0; // delayed by one active cycle (not skipped)
//    reg  read_in_progress_or=0; // read_in_progress || read_in_progress_d

      if   (rst) read_left <= 0;
      else if (start_read_burst_w) read_left <= arlen_out[3:0]; // precedence over inc
182
      else if (bram_reg_re_w)      read_left <= read_left-1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 4-bit target.
183 184 185 186 187 188 189 190 191 192 193 194 195
            
      if   (rst)                   read_address <= {ADDRESS_BITS{1'b0}};
      else if (start_read_burst_w) read_address <= araddr_out[ADDRESS_BITS-1:0]; // precedence over inc
      else if (bram_reg_re_w)      read_address <= next_rd_address_w;
      
      if      (rst)                                  rvalid <= 1'b0;
      else if (bram_reg_re_w && read_in_progress_d)  rvalid <= 1'b1;
      else if (rready)                               rvalid <= 1'b0;

      if      (rst)                rlast <= 1'b0;
      else if (last_in_burst_d_w)  rlast <= 1'b1;
      else if (rready)             rlast <= 1'b0;
    end
196
    always @ (posedge  aclk) begin //SuppressThisWarning ISExst Assignment to bram_reg_re_0 ignored, since the identifier is never used
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
//        bram_reg_re_0 <= read_in_progress_w && !pre_rvalid_w;

        bram_reg_re_0 <= (ar_nempty && !read_in_progress) || (read_in_progress && !read_in_progress);
        
        last_in_burst_1 <= read_in_progress_w && pre_left_zero_w;
        
        last_in_burst_0 <= read_in_progress_w && !pre_rvalid_w && pre_left_zero_w;
        
        start_read_burst_1 <= !read_in_progress_w || pre_left_zero_w;
        start_read_burst_0 <= !read_in_progress_w || (!pre_rvalid_w && pre_left_zero_w);
        
        if (start_read_burst_w) pre_rid0[11:0] <= arid_out[11:0];
        if (bram_reg_re_w)      pre_rid[11:0]  <= pre_rid0[11:0];
        if (bram_reg_re_w)      rid[11:0] <= pre_rid[11:0];
    end
    // reducing rready combinatorial delay
    assign  pre_left_zero_w=start_read_burst_w?(arlen_out[3:0]==4'b0):(bram_reg_re_w && (read_left==4'b0001));
//    assign bram_reg_re_w=     read_in_progress && (!rvalid || rready);

216
    assign bram_reg_re_w=   dev_ready && read_in_progress_or && (!rvalid || rready); // slower/simplier
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
//    assign bram_reg_re_w=   rready? read_in_progress : bram_reg_re_0; // faster - more verification
    
    
    assign last_in_burst_w=bram_reg_re_w && (read_left==4'b0); // slower/simplier
//    assign last_in_burst_w=rready? (read_in_progress && (read_left==4'b0)): (bram_reg_re_0 && (read_left==4'b0));
//    assign last_in_burst_w=rready? last_in_burst_1: last_in_burst_0; // faster (unfinished) - more verification


    assign start_read_burst_w=ar_nempty && (!read_in_progress || (bram_reg_re_w && (read_left==4'b0))); // reduce delay from rready
//    assign start_read_burst_w=ar_nempty && (!read_in_progress || ((rready? read_in_progress : bram_reg_re_0) && (read_left==4'b0)));

//    assign start_read_burst_w=
//    rready?
//    (ar_nempty && (!read_in_progress || ((read_in_progress) && (read_left==4'b0)))):
//    (ar_nempty && (!read_in_progress || ((bram_reg_re_0   ) && (read_left==4'b0))));

/*
    assign start_read_burst_w=
    ar_nempty*(rready?
    (!read_in_progress || (read_left==4'b0)):
    ((!read_in_progress || ((bram_reg_re_0   ) && (read_left==4'b0)))));
*/    
//    assign start_read_burst_w=  ar_nempty && (rready?start_read_burst_1:start_read_burst_0);

241
fifo_same_clock   #( .DATA_WIDTH(ADDRESS_BITS+20),.DATA_DEPTH(4))    
242 243 244
    raddr_i (
        .rst(rst),
        .clk(aclk),
245
        .sync_rst(1'b0), // input
246 247 248
        .we(arvalid && arready),
        .re(start_read_burst_w),
        .data_in({arid[11:0], arburst[1:0],arsize[1:0],arlen[3:0],araddr[ADDRESS_BITS+1:2]}),
249
        .data_out({arid_out[11:0], arburst_out[1:0],arsize_out[1:0],arlen_out[3:0],araddr_out[ADDRESS_BITS-1:0]}), //SuppressThisWarning ISExst Assignment to arsize ignored, since the identifier is never used
250 251 252 253
        .nempty(ar_nempty),
        .half_full(ar_half_full)
    );
endmodule