axibram_write.v 10.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*******************************************************************************
 * Module: axibram_write
 * Date:2014-03-18  
 * Author: Andrey Filippov
 * Description: Read block RAM memory (or memories?) over AXI PS Master GP0
 * Memory is supposed to be fast enough
 *
 * Copyright (c) 2014 Elphel, Inc.
 * axibram_write.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_write.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/> .
 *******************************************************************************/
22
//`define DEBUG_FIFO 1 
23
`include "system_defines.vh" 
24 25 26
`ifdef DEBUG_FIFO
  `undef DEBUG_FIFO
`endif
27
module  axibram_write #(
28 29 30
    parameter ADDRESS_BITS = 10 // number of memory address bits
)(
   input         aclk,    // clock - should be buffered
Andrey Filippov's avatar
Andrey Filippov committed
31
   input         arst,     // @aclk sync reset, active high
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
   
// AXI Write Address
   input  [31:0] awaddr,  // AWADDR[31:0], input
   input         awvalid, // AWVALID, input
   output        awready, // AWREADY, output
   input  [11:0] awid,    // AWID[11:0], input
   input  [ 3:0] awlen,   // AWLEN[3:0], input
   input  [ 1:0] awsize,  // AWSIZE[1:0], input
   input  [ 1:0] awburst, // AWBURST[1:0], input
// AXI PS Master GP0: Write Data
   input  [31:0] wdata,   // WDATA[31:0], input
   input         wvalid,  // WVALID, input
   output        wready,  // WREADY, output
   input  [11:0] wid,     // WID[11:0], input
   input         wlast,   // WLAST, input
   input  [ 3:0] wstb,    // WSTRB[3:0], input
// AXI PS Master GP0: Write Responce
   output        bvalid,  // BVALID, output
   input         bready,  // BREADY, input
   output [11:0] bid,     // BID[11:0], output
   output [ 1:0] bresp,    // BRESP[1:0], output
   
54 55 56 57 58
// BRAM (and other write modules) interface
   output [ADDRESS_BITS-1:0] pre_awaddr, // same as awaddr_out, early address to decode and return dev_ready
   output        start_burst, // start of write burst, valid pre_awaddr, save externally to control ext. dev_ready multiplexer
   input         dev_ready,   // extrernal combinatorial ready signal, multiplexed from different sources according to pre_awaddr@start_burst
    
59 60
   output        bram_wclk,
   output  [ADDRESS_BITS-1:0] bram_waddr,
61
   output        bram_wen,    // external memory wreite enable, (internally combined with registered dev_ready
62 63
   output  [3:0] bram_wstb, 
   output [31:0] bram_wdata
Andrey Filippov's avatar
Andrey Filippov committed
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
`ifdef DEBUG_FIFO
    ,
        output    waddr_under,
        output    wdata_under,
        output    wresp_under, 
        output    waddr_over,
        output    wdata_over,
        output    wresp_over,
        
        output [3:0]   waddr_wcount, 
        output [3:0]   waddr_rcount, 
        output [3:0]   waddr_num_in_fifo, 
        
        output [3:0]   wdata_wcount, 
        output [3:0]   wdata_rcount, 
        output [3:0]   wdata_num_in_fifo, 
        
        output [3:0]   wresp_wcount, 
        output [3:0]   wresp_rcount, 
        output [3:0]   wresp_num_in_fifo,
        
        output [3:0]   wleft,
        
        output [3:0]   wlength,
        output reg [3:0] wlen_in_dbg  

`endif   
91
);
92
//    wire rst=~aresetn;
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
// **** Write channel: ****
    wire aw_nempty;
    wire aw_half_full;
    assign awready=~aw_half_full;
    wire [ 1:0] awburst_out;
    // SuppressWarnings VEditor all 
    wire [ 1:0] awsize_out; // not used
    wire [ 3:0] awlen_out;
    wire [ADDRESS_BITS-1:0] awaddr_out;
    // SuppressWarnings VEditor all 
    wire [11:0] awid_out;   // not used
    wire w_nempty;
    wire w_half_full;
    assign wready=~w_half_full;
    wire [31:0] wdata_out;
    // SuppressWarnings VEditor all 
    wire        wlast_out;   // not used
    wire [ 3:0] wstb_out;    // WSTRB[3:0], input
    wire [11:0] wid_out;
    reg         write_in_progress=0;
    reg  [ADDRESS_BITS-1:0] write_address;       // transfer address (not including lower bits 
Andrey Filippov's avatar
Andrey Filippov committed
114
    reg  [ 3:0] write_left;          // number of write transfers
115 116 117 118
// will ignore arsize - assuming always 32 bits  (a*size[2:0]==2)
    reg  [ 1:0] wburst;             // registered burst type
    reg  [ 3:0] wlen;               // registered awlen type (for wrapped over transfers)
    wire [ADDRESS_BITS-1:0] next_wr_address_w;  // next transfer address;
119
    wire        bram_we_w; //,bram_we_nonmasked;   // write BRAM memory non-masked - should be combined with  
120 121
    wire        start_write_burst_w;
    wire        write_in_progress_w;
122 123 124 125 126 127
    
    wire        aw_nempty_ready; // aw_nempty and device ready
    wire        w_nempty_ready; // w_nempty and device ready
    assign aw_nempty_ready=aw_nempty && dev_ready_r; // should it be dev_ready?
    assign w_nempty_ready=w_nempty && dev_ready_r; // should it be dev_ready?
    
128
    reg         dev_ready_r;        // device, selected at start burst
129
    assign      next_wr_address_w= //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 13-bit target.
130 131 132 133
      wburst[1]?
        (wburst[0]? {ADDRESS_BITS{1'b0}}:((write_address[ADDRESS_BITS-1:0]+1) & {{(ADDRESS_BITS-4){1'b1}}, ~wlen[3:0]})):
        (wburst[0]? (write_address[ADDRESS_BITS-1:0]+1):(write_address[ADDRESS_BITS-1:0]));
        
134
    assign      bram_we_w=         w_nempty_ready &&  write_in_progress;
135 136 137 138 139
//    assign start_write_burst_w=w_nempty_ready && aw_nempty_ready && (!write_in_progress || (w_nempty_ready && (write_left[3:0]==4'b0)));
//    assign write_in_progress_w=w_nempty_ready && aw_nempty_ready || (write_in_progress && !(w_nempty_ready && (write_left[3:0]==4'b0))); 
    // adding wlast_out to take precedence over (write_left[3:0]==4'b0), maybe wlast_out itself is sufficient
    assign start_write_burst_w=w_nempty_ready && aw_nempty_ready && (!write_in_progress || (w_nempty_ready && ((write_left[3:0]==4'b0) || wlast_out)));
    assign write_in_progress_w=w_nempty_ready && aw_nempty_ready || (write_in_progress && !(w_nempty_ready && ((write_left[3:0]==4'b0) || wlast_out))); 
140
    
Andrey Filippov's avatar
Andrey Filippov committed
141 142
    always @ (posedge  aclk) begin
      if   (arst)                   wburst[1:0] <= 0;
143 144
      else if (start_write_burst_w) wburst[1:0] <= awburst_out[1:0];

Andrey Filippov's avatar
Andrey Filippov committed
145
      if   (arst)                   wlen[3:0] <= 0;
146 147
      else if (start_write_burst_w) wlen[3:0] <= awlen_out[3:0];
    
Andrey Filippov's avatar
Andrey Filippov committed
148 149
      if   (arst) write_in_progress <= 0;
      else        write_in_progress <= write_in_progress_w;
150

Andrey Filippov's avatar
Andrey Filippov committed
151
      if   (arst)                   write_left <= 0;
152
      else if (start_write_burst_w) write_left <= awlen_out[3:0]; // precedence over inc
153
      else if (bram_we_w)           write_left <= write_left-1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 4-bit target.
154
            
Andrey Filippov's avatar
Andrey Filippov committed
155
      if   (arst)                   write_address <= {ADDRESS_BITS{1'b0}};
156 157
      else if (start_write_burst_w) write_address <= awaddr_out[ADDRESS_BITS-1:0]; // precedence over inc
      else if (bram_we_w)           write_address <= next_wr_address_w;
158
      
Andrey Filippov's avatar
Andrey Filippov committed
159 160
      if (arst) dev_ready_r <= 1'b0;
      else      dev_ready_r <= dev_ready;
161
    end
162
// **** Write response channel ****    
163 164 165
    wire [ 1:0] bresp_in;
    assign bresp_in=2'b0;

166 167 168 169
// external memory interface (write only)
   assign pre_awaddr=awaddr_out[ADDRESS_BITS-1:0];
   assign start_burst=start_write_burst_w;
   
170 171 172 173 174 175
   assign  bram_wclk  = aclk;
   assign  bram_waddr = write_address[ADDRESS_BITS-1:0];
   assign  bram_wen   = bram_we_w; 
   assign  bram_wstb   = wstb_out[3:0]; 
   assign  bram_wdata = wdata_out[31:0];
    
Andrey Filippov's avatar
Andrey Filippov committed
176 177 178 179 180 181 182 183
 `ifdef DEBUG_FIFO
    assign wleft=write_left;
    assign wlength[3:0]=wlen[3:0];
    always @ (posedge aclk) begin
        wlen_in_dbg <= awlen[3:0];
    end
 `endif  
fifo_same_clock   #( .DATA_WIDTH(20+ADDRESS_BITS),.DATA_DEPTH(4))
184
    waddr_i (
Andrey Filippov's avatar
Andrey Filippov committed
185
        .rst       (1'b0), //rst),
Andrey Filippov's avatar
Andrey Filippov committed
186
        .clk       (aclk),
Andrey Filippov's avatar
Andrey Filippov committed
187
        .sync_rst  (arst),
Andrey Filippov's avatar
Andrey Filippov committed
188 189
        .we        (awvalid && awready),
        .re        (start_write_burst_w),
190
        .data_in   ({awid[11:0], awburst[1:0],awsize[1:0],awlen[3:0],awaddr[ADDRESS_BITS+1:2]}),
Andrey Filippov's avatar
Andrey Filippov committed
191 192 193 194 195 196 197 198 199 200 201
        .data_out  ({awid_out[11:0], awburst_out[1:0],awsize_out[1:0],awlen_out[3:0],awaddr_out[ADDRESS_BITS-1:0]}),  //SuppressThisWarning ISExst Assignment to awsize_out ignored, since the identifier is never used
        .nempty    (aw_nempty),
        .half_full (aw_half_full)
`ifdef DEBUG_FIFO
        ,
        .under      (waddr_under), // output reg 
        .over       (waddr_over), // output reg
        .wcount     (waddr_wcount), // output[3:0] reg 
        .rcount     (waddr_rcount), // output[3:0] reg 
        .num_in_fifo(waddr_num_in_fifo) // output[3:0] 
`endif         
202
    );
203
fifo_same_clock   #( .DATA_WIDTH(49),.DATA_DEPTH(4))    
204
    wdata_i (
Andrey Filippov's avatar
Andrey Filippov committed
205
        .rst(1'b0), //rst),
206
        .clk(aclk),
Andrey Filippov's avatar
Andrey Filippov committed
207
        .sync_rst  (arst),
208 209 210
        .we(wvalid && wready),
        .re(bram_we_w), //start_write_burst_w), // wrong
        .data_in({wid[11:0],wlast,wstb[3:0],wdata[31:0]}),
211
        .data_out({wid_out[11:0],wlast_out,wstb_out[3:0],wdata_out[31:0]}), //SuppressThisWarning ISExst Assignment to wlast ignored, since the identifier is never used
212 213
        .nempty(w_nempty),
        .half_full(w_half_full)
Andrey Filippov's avatar
Andrey Filippov committed
214 215 216 217 218 219 220 221
`ifdef DEBUG_FIFO
        ,
        .under      (wdata_under), // output reg 
        .over       (wdata_over), // output reg
        .wcount     (wdata_wcount), // output[3:0] reg 
        .rcount     (wdata_rcount), // output[3:0] reg 
        .num_in_fifo(wdata_num_in_fifo) // output[3:0] 
`endif
222
    );
Andrey Filippov's avatar
Andrey Filippov committed
223 224 225 226
//debugging - slow down bresp
reg was_bresp_re=0;
wire bresp_re;
assign bresp_re=bready && bvalid && !was_bresp_re;
Andrey Filippov's avatar
Andrey Filippov committed
227 228 229
always @ (posedge aclk) begin
    if (arst) was_bresp_re<=0;
    else      was_bresp_re <= bresp_re;
Andrey Filippov's avatar
Andrey Filippov committed
230 231
end
  
232
fifo_same_clock  #( .DATA_WIDTH(14),.DATA_DEPTH(4))    
233
    wresp_i (
Andrey Filippov's avatar
Andrey Filippov committed
234
        .rst(1'b0), //rst),
235
        .clk(aclk),
Andrey Filippov's avatar
Andrey Filippov committed
236
        .sync_rst  (arst),
237
        .we(bram_we_w &&((write_left[3:0]==4'b0) || wlast_out)), // added ((write_left[3:0]==4'b0) || wlast_out) - only last wrtite -> bresp
Andrey Filippov's avatar
Andrey Filippov committed
238 239
//        .re(bready && bvalid),
        .re(bresp_re), // not allowing RE next cycle after bvalid
240 241 242 243
        .data_in({wid_out[11:0],bresp_in[1:0]}),
        .data_out({bid[11:0],bresp[1:0]}),
        .nempty(bvalid),
        .half_full()
Andrey Filippov's avatar
Andrey Filippov committed
244 245 246 247 248 249 250 251 252
`ifdef DEBUG_FIFO
        ,
        .under      (wresp_under), // output reg 
        .over       (wresp_over), // output reg
        .wcount     (wresp_wcount), // output[3:0] reg 
        .rcount     (wresp_rcount), // output[3:0] reg 
        .num_in_fifo(wresp_num_in_fifo) // output[3:0] 
        
`endif
253 254 255
    );

endmodule