axibram_read.v 12.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*!
 * <b>Module:</b>axibram_read
 * @file axibram_read.v
 * @date 2014-03-18  
 * @author Andrey Filippov
 *
 * @brief Read block RAM memory over AXI PS Master GP0
 *
 * @copyright Copyright (c) 2014 Elphel, Inc.
 *
 * <b>License:</b>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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/> .
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
 // Check that this fix did not break anything:
40
`include "system_defines.vh" 
41
`define USE_SHORT_REN_REGEN 
42
module  axibram_read #(
43 44 45
    parameter ADDRESS_BITS = 10 // number of memory address bits
)(
   input         aclk,    // clock - should be buffered
Andrey Filippov's avatar
Andrey Filippov committed
46 47
//   input         rst, // reset, active high
   input         arst, // @posedge aclk  sync reset, active high
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
// 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  [ 3:0] arlen,   // ARLEN[3:0], input
   input  [ 1:0] arsize,  // ARSIZE[1:0], input
   input  [ 1:0] arburst, // ARBURST[1: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,
63 64 65 66 67 68
// 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   
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
   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;
86
//    wire rst=~aresetn;
87 88 89 90 91 92 93 94 95 96
    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;
97
    assign      next_rd_address_w= //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 13-bit target.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
      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;
128 129 130 131
    // TODO: Speed up by moving registers
    // SuppressWarnings VEditor all - not yet used 
    reg bram_reg_re_0;
    // SuppressWarnings VEditor all - not yet used 
132
    reg last_in_burst_1;
133
    // SuppressWarnings VEditor all - not yet used 
134
    reg last_in_burst_0;
135
    // SuppressWarnings VEditor all - not yet used 
136
    reg start_read_burst_0;
137
    // SuppressWarnings VEditor all - not yet used 
138 139 140
    reg start_read_burst_1;
    reg [11:0] pre_rid0;
    reg [11:0] pre_rid;
141
    
142 143 144 145 146
// 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
147 148
   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
149
   
150
`ifdef USE_SHORT_REN_REGEN 
151
   reg bram_regen_r;
Andrey Filippov's avatar
Andrey Filippov committed
152
//   assign  bram_ren =   bram_reg_re_w && !pre_last_in_burst_r ;     // read port enable
153 154
///   assign  bram_ren = read_in_progress;
   assign  bram_ren = read_in_progress && dev_ready;
155 156
   assign  bram_regen = bram_regen_r;     // output register enable
`else
157 158
   assign  bram_ren =   bram_reg_re_w;     // read port enable
   assign  bram_regen = bram_reg_re_w;     // output register enable
159
`endif   
160
   
161 162
   assign  rdata[31:0] = bram_rdata;    // data out

Andrey Filippov's avatar
Andrey Filippov committed
163
    always @ (posedge  aclk) begin
164
`ifdef USE_SHORT_REN_REGEN   
Andrey Filippov's avatar
Andrey Filippov committed
165
      if   (arst)  bram_regen_r <= 0;
166 167 168
      else        bram_regen_r <=  bram_ren;
`endif    
   
Andrey Filippov's avatar
Andrey Filippov committed
169
      if   (arst)                   pre_last_in_burst_r <= 0;
170 171 172
//      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);
    
Andrey Filippov's avatar
Andrey Filippov committed
173
      if   (arst)                   rburst[1:0] <= 0;
174 175
      else if (start_read_burst_w) rburst[1:0] <= arburst_out[1:0];

Andrey Filippov's avatar
Andrey Filippov committed
176
      if   (arst)                   rlen[3:0] <= 0;
177 178
      else if (start_read_burst_w) rlen[3:0] <= arlen_out[3:0];
    
Andrey Filippov's avatar
Andrey Filippov committed
179
      if   (arst) read_in_progress <= 0;
180 181
      else       read_in_progress <= read_in_progress_w;

Andrey Filippov's avatar
Andrey Filippov committed
182
      if   (arst)                read_in_progress_d <= 0;
183 184 185
//      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;
      
Andrey Filippov's avatar
Andrey Filippov committed
186
      if   (arst) read_in_progress_or <= 0;
187 188 189 190 191 192 193 194
//      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

Andrey Filippov's avatar
Andrey Filippov committed
195
      if      (arst)               read_left <= 0;
196
      else if (start_read_burst_w) read_left <= arlen_out[3:0]; // precedence over inc
197
      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.
198
            
Andrey Filippov's avatar
Andrey Filippov committed
199
      if      (arst)               read_address <= {ADDRESS_BITS{1'b0}};
200 201 202
      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;
      
Andrey Filippov's avatar
Andrey Filippov committed
203
      if      (arst)                                 rvalid <= 1'b0;
204 205 206
      else if (bram_reg_re_w && read_in_progress_d)  rvalid <= 1'b1;
      else if (rready)                               rvalid <= 1'b0;

Andrey Filippov's avatar
Andrey Filippov committed
207
      if      (arst)               rlast <= 1'b0;
208 209 210
      else if (last_in_burst_d_w)  rlast <= 1'b1;
      else if (rready)             rlast <= 1'b0;
    end
Andrey Filippov's avatar
Andrey Filippov committed
211
    
212
    always @ (posedge  aclk) begin //SuppressThisWarning ISExst Assignment to bram_reg_re_0 ignored, since the identifier is never used
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
//        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);

232
    assign bram_reg_re_w=   dev_ready && read_in_progress_or && (!rvalid || rready); // slower/simplier
233 234
//    assign bram_reg_re_w=   rready? read_in_progress : bram_reg_re_0; // faster - more verification
    
235
        assign last_in_burst_w=bram_reg_re_w && (read_left==4'b0); // slower/simplier
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
//    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);

256
fifo_same_clock   #( .DATA_WIDTH(ADDRESS_BITS+20),.DATA_DEPTH(4))    
257
    raddr_i ( 
Andrey Filippov's avatar
Andrey Filippov committed
258
        .rst(1'b0),
259
        .clk(aclk),
Andrey Filippov's avatar
Andrey Filippov committed
260
        .sync_rst(arst),
261 262
        .we(arvalid && arready),
        .re(start_read_burst_w),
263
        .data_in({arid[11:0], arburst[1:0],arsize[1:0],arlen[3:0],araddr[ADDRESS_BITS+1:2]}), 
264
        .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
265 266 267 268
        .nempty(ar_nempty),
        .half_full(ar_half_full)
    );
endmodule