axi_ahci_regs.v 28.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*******************************************************************************
 * Module: axi_ahci_regs
 * Date:2015-12-29  
 * Author: Andrey Filippov
 * Description: Registers for single-port AHCI over AXI implementation
 * Combination of PCI Headers, PCI power management, and HBA memory
 * 128 DWORD registers 
 * Registers, with bits being RO, RW, RWC, RW1
 *
 * Copyright (c) 2015 Elphel, Inc .
 * axi_ahci_regs.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.
 *
 *  axi_ahci_regs.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/> .
23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * 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"
 * files and/or simulating the code, the copyright holders of this Program give
 * 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
 * charge, and there is no dependence on any encrypted modules for simulating of
 * 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.
36 37 38 39 40
 *******************************************************************************/
`timescale 1ns/1ps


module  axi_ahci_regs#(
41
//    parameter ADDRESS_BITS = 8 // number of memory address bits
42
    parameter ADDRESS_BITS =  10, // number of memory address bits - now fixed. Low half - RO/RW/RWC,RW1 (2-cycle write), 2-nd just RW (single-cycle)
Andrey Filippov's avatar
Andrey Filippov committed
43 44
    parameter HBA_RESET_BITS = 9, // duration of HBA reset in aclk periods (9: ~10usec)
    parameter RESET_TO_FIRST_ACCESS = 1 // keep port reset until first R/W any register by software
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
)(
    input             aclk,    // clock - should be buffered
    input             arst,     // @aclk sync reset, active high
   
// 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
64
// AXI PS Master GP0: Write response
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    output            bvalid,  // BVALID, output
    input             bready,  // BREADY, input
    output     [11:0] bid,     // BID[11:0], output
    output     [ 1:0] bresp,    // BRESP[1:0], output
// 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            rvalid,  // RVALID, output
    input             rready,  // RREADY, input
    output     [11:0] rid,     // RID[11:0], output
    output            rlast,   // RLAST, output
    output     [ 1:0] rresp,   // RRESP
   
// HBA interface
// 1. Notification of data written @ hba_clk
    output [ADDRESS_BITS-1:0] soft_write_addr,  // register address written by software
    output             [31:0] soft_write_data,  // register data written (after applying wstb and type (RO, RW, RWC, RW1)
89
    output                    soft_write_en,    // write enable for data write
90
    // Apply next 2 resets and arst OR-ed to SATA.extrst
91 92
    output                    hba_arst,          // hba async reset (currently does ~ the same as port reset)
    output                    port_arst,         // port0 async reset by software
93
    output                    port_arst_any,     // port0 async reset by POR or software
94

95
// 2. HBA R/W registers, use hba clock
96 97
    input                     hba_clk,          // SATA clock, now 75MHz
    input                     hba_rst,          // when PLL locked, SATA PHY reset is over, this signal is released
98 99 100 101 102
    input  [ADDRESS_BITS-1:0] hba_addr,
    input                     hba_we,
//   input               [3:0] hba_wstb, Needed?
    input               [1:0] hba_re, // [0] - re, [1] - regen
    input              [31:0] hba_din,
103 104
    output             [31:0] hba_dout,
    
105 106 107 108 109 110 111
// Program FSM memory
    output reg         [17:0] pgm_ad, // @aclk, address/data to program the AHCI FSM
    output reg                pgm_wa, // @aclk, address strobe to program the AHCI FSM
    output reg                pgm_wd, // @aclk, data strobe to program the AHCI FSM
    
    
    
112 113 114
//  other control signals
    output reg         [ 3:0] afi_wcache,
    output reg         [ 3:0] afi_rcache,
115 116
    output                    afi_cache_set,
    output                    was_hba_rst,    // last reset was hba reset (not counting system reset)
117
    output                    was_port_rst,    // last reset was port reset
118 119 120 121
    input              [31:0] debug_in0,
    input              [31:0] debug_in1,
    input              [31:0] debug_in2,
    input              [31:0] debug_in3
Andrey Filippov's avatar
Andrey Filippov committed
122 123 124 125 126 127 128 129
`ifdef USE_DRP
   ,output reg                drp_en, // @aclk strobes drp_ad
    output reg                drp_we,
    output reg         [14:0] drp_addr,       
    output reg         [15:0] drp_di,
    input                     drp_rdy,
    input              [15:0] drp_do 
`endif    
130 131 132 133 134
`ifdef USE_DATASCOPE
// Datascope interface (write to memory that can be software-read)
   ,input                     datascope_clk,
    input  [ADDRESS_BITS-1:0] datascope_waddr,      
    input                     datascope_we,
135 136 137 138 139 140
    input              [31:0] datascope_di,
    
    input                     datascope1_clk,
    input  [ADDRESS_BITS-1:0] datascope1_waddr,      
    input                     datascope1_we,
    input              [31:0] datascope1_di
141
`endif    
142
);
Andrey Filippov's avatar
Andrey Filippov committed
143 144 145 146 147 148
`ifdef USE_DRP
    localparam DRP_ADDR =     'h3fb;
    reg                [15:0] drp_read_data;
    reg                       drp_read_r;
    reg                       drp_ready_r;
`endif
149
`ifdef USE_DATASCOPE
150 151
//    localparam AXIBRAM_BITS = ADDRESS_BITS + 1; // number of axi address outputs (one more than ADDRESS_BITS when using datascope)
    localparam AXIBRAM_BITS = ADDRESS_BITS + 2; // number of axi address outputs (one more than ADDRESS_BITS when using datascope)
152 153
    wire               [31:0] datascope_rdata;
    reg                [1:0]  datascope_sel;    // read datascope memory instead of the registers
154 155
    wire               [31:0] datascope1_rdata;
    reg                [1:0]  datascope1_sel;    // read datascope memory instead of the registers
156
    always @ (posedge aclk) begin
157 158
        datascope_sel <=  {datascope_sel[0],  ~bram_raddr[ADDRESS_BITS+1] &  bram_raddr[ADDRESS_BITS]};
        datascope1_sel <= {datascope1_sel[0],  bram_raddr[ADDRESS_BITS+1] & ~bram_raddr[ADDRESS_BITS]};
159 160 161 162
    end
`else 
    localparam AXIBRAM_BITS =  ADDRESS_BITS; // number of axi address outputs (one more than ADDRESS_BITS when using datascope)
`endif
163
`include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams
164
    wire   [AXIBRAM_BITS-1:0] bram_waddr;
165
//    wire   [ADDRESS_BITS-1:0] pre_awaddr;
166
    wire   [AXIBRAM_BITS-1:0] bram_raddr;
167 168 169 170 171 172 173 174
    wire               [31:0] bram_rdata;
    wire                      pre_bram_wen; // one cycle ahead of bram_wen, nut not masked by dev_ready
    wire                      bram_wen;
    wire               [ 3:0] bram_wstb; 
    wire               [31:0] bram_wdata; 
    wire   [ADDRESS_BITS-1:0] bram_addr; 
   

175 176 177
    wire             [1:0] bram_ren;
    reg                    write_busy_r;
    wire                   write_start_burst;
178
//    wire         nowrite;          // delay write in read-modify-write register accesses
Andrey Filippov's avatar
Andrey Filippov committed
179 180
///    wire                   write_busy_w = write_busy_r || write_start_burst;
    wire                   write_busy_w = write_busy_r || write_start_burst || bram_wen_r;
181 182 183 184 185 186 187 188 189 190
    reg             [31:0] bram_wdata_r;
    reg             [31:0] bram_rdata_r;
//    reg                    bram_wen_d;
    wire            [63:0] regbit_type;
    wire            [31:0] ahci_regs_di;
    reg             [ 3:0] bram_wstb_r;
    reg                    bram_wen_r;
//    wire  [31:0] wmask = {{8{bram_wstb[3]}},{8{bram_wstb[2]}},{8{bram_wstb[1]}},{8{bram_wstb[0]}}};
    wire            [31:0] wmask = {{8{bram_wstb_r[3]}},{8{bram_wstb_r[2]}},{8{bram_wstb_r[1]}},{8{bram_wstb_r[0]}}};
    reg [ADDRESS_BITS-1:0] bram_waddr_r;
191
    
Andrey Filippov's avatar
Andrey Filippov committed
192
    reg [HBA_RESET_BITS-1:0] hba_reset_cntr; // time to keep hba_reset_r active after writing to GHC.HR
193 194
    reg                      hba_rst_r;      // hba _reset (currently does ~ the same as port reset)
    reg                      port_rst_r;     // port _reset by software
Andrey Filippov's avatar
Andrey Filippov committed
195
    reg                      port_arst_any_r = 1;   // port _reset by software or POR
196
    
197
    wire                   high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write
198
    wire                   afi_cache_set_w = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__AFI_CACHE__WR_CM__ADDR);
199 200
    wire                   pgm_fsm_set_w =   bram_wen_r && !high_sel && (bram_addr == HBA_PORT__PGM_AHCI_SM__PGM_AD__ADDR);
    wire                   pgm_fsm_and_w = |(ahci_regs_di & HBA_PORT__PGM_AHCI_SM__AnD__MASK);
201
    
202
    wire                   set_hba_rst =  bram_wen_r && !high_sel && (bram_addr == GHC__GHC__HR__ADDR) && (ahci_regs_di & GHC__GHC__HR__MASK);
203
    localparam HBA_PORT__PxSCTL__DET__MASK01 = HBA_PORT__PxSCTL__DET__MASK & ~1; // == 'he
204
    wire                   set_port_rst = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__PxSCTL__DET__ADDR) &&
205
                                          ((ahci_regs_di & HBA_PORT__PxSCTL__DET__MASK01) == 0); // writing only 0/1
206 207 208 209 210
                                                                 //  in lower 4 bits
    
    wire                   port_rst_on = set_port_rst && ahci_regs_di[0];
    reg                    was_hba_rst_aclk;     // last reset was hba reset (not counting system reset)
    reg                    was_port_rst_aclk;    // last reset was port reset
Andrey Filippov's avatar
Andrey Filippov committed
211 212 213 214 215
    reg             [2:0]  was_hba_rst_r;        // last reset was hba reset (not counting system reset)
    reg             [2:0]  was_port_rst_r;       // last reset was port reset
    reg             [2:0]  arst_r = ~0;          // previous state of arst
    reg                    wait_first_access = RESET_TO_FIRST_ACCESS;    // keep port reset until first access
    wire                   any_access = bram_wen_r || bram_ren[0];
216
    reg                    debug_rd_r = 0;
217
    reg             [31:0] debug_r;
218
    
219

220
    assign bram_addr =     bram_ren[0] ? bram_raddr[ADDRESS_BITS-1:0] : (bram_wen_r ? bram_waddr_r : bram_waddr[ADDRESS_BITS-1:0]);
Andrey Filippov's avatar
Andrey Filippov committed
221
    
Andrey Filippov's avatar
Andrey Filippov committed
222 223 224 225 226
    assign hba_arst =      hba_rst_r;       // hba _reset (currently does ~ the same as port reset)
    assign port_arst =     port_rst_r;     // port _reset by software
    assign port_arst_any = port_arst_any_r;
    assign was_hba_rst =   was_hba_rst_r[0]; 
    assign was_port_rst =  was_port_rst_r[0];
227
    
Andrey Filippov's avatar
Andrey Filippov committed
228
    
229
    always @(posedge aclk) begin
Andrey Filippov's avatar
Andrey Filippov committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
`ifdef USE_DRP
    if (bram_waddr == DRP_ADDR) begin
        drp_di <=   bram_wdata[15: 0];
        drp_addr <= bram_wdata[30:16];
//        drp_we <=   bram_wdata[31];
    end
    
    drp_en <= (bram_waddr == DRP_ADDR);
    drp_we <= (bram_waddr == DRP_ADDR) && bram_wdata[31];
    
    if (arst || (bram_waddr == DRP_ADDR)) drp_ready_r <= 0;
    else if (drp_rdy)                     drp_ready_r <= 1;
    
    if (drp_rdy)                          drp_read_data <= drp_do;
    
    if (bram_ren[0])                      drp_read_r <= (bram_raddr == DRP_ADDR);
    
`endif    

Andrey Filippov's avatar
Andrey Filippov committed
249
       
250 251 252 253 254 255
        if      (arst)              write_busy_r <= 0;
        else if (write_start_burst) write_busy_r <= 1;
        else if (!pre_bram_wen)     write_busy_r <= 0;

        if (bram_wen)               bram_wdata_r <= bram_wdata;
        
256 257 258 259
        bram_wstb_r <= {4{bram_wen}} & bram_wstb;
        
        bram_wen_r <= bram_wen;
        
260
        if (bram_wen) bram_waddr_r <= bram_waddr[ADDRESS_BITS-1:0];
261 262 263 264 265 266 267 268 269 270
`ifndef NO_DEBUG_OUT        
    `ifdef USE_DATASCOPE        
            if (bram_ren[0])            debug_rd_r <= (&bram_raddr[ADDRESS_BITS-1:4]) &&
    //                                                  (bram_raddr[3:2] == 0) &&
                                                      !bram_raddr[ADDRESS_BITS]; // 
    `else
            if (bram_ren[0])            debug_rd_r <= (&bram_raddr[ADDRESS_BITS-1:4]); // &&
    //                                                  (bram_raddr[3:2] == 0); // 
    `endif                                                  
`endif // `else `ifdef NO_DEBUG_OUT
271 272 273 274
        if (bram_ren[0])            debug_r <= bram_raddr[1]? (bram_raddr[0] ? debug_in3: debug_in2):
                                                              (bram_raddr[0] ? debug_in1: debug_in0);
        

Andrey Filippov's avatar
Andrey Filippov committed
275 276 277 278 279 280
`ifdef USE_DRP
        if (bram_ren[1])            bram_rdata_r <= drp_read_r? {drp_ready_r, 15'b0,drp_read_data}:
                                                                (debug_rd_r? debug_r : bram_rdata);
`else
        if (bram_ren[1])            bram_rdata_r <= debug_rd_r? debug_r : bram_rdata;
`endif
281 282
    end

283 284
    //debug_rd_r    

285 286 287
    generate
        genvar i;
        for (i=0; i < 32; i=i+1) begin: bit_type_block
288
            assign ahci_regs_di[i] = (regbit_type[2*i+1] && wmask[i] && !high_sel)?
289 290 291
                                       ((regbit_type[2*i] && wmask[i])?
                                          (bram_rdata[i] || bram_wdata_r[i]):   // 3: RW1
                                          (bram_rdata[i] && !bram_wdata_r[i])): // 2: RWC
292 293
                                       (((regbit_type[2*i] && wmask[i]) || high_sel)?
                                          (bram_wdata_r[i]):                    // 1: RW write new data - get here for high_sel
294 295 296 297
                                          (bram_rdata[i]));                     // 0: R0 (keep old data)
        end
    endgenerate    

Andrey Filippov's avatar
Andrey Filippov committed
298 299 300 301 302 303 304 305 306 307 308
//    always @ (posedge aclk or posedge arst) begin
    always @ (posedge aclk) begin
        if      (arst)                      wait_first_access <= RESET_TO_FIRST_ACCESS;
        else if (any_access)                wait_first_access <= 0;
    
        if      (arst)                            port_arst_any_r <= 1;
        else if (set_port_rst)                    port_arst_any_r <= ahci_regs_di[0]; // write "1" - reset on, write 0 - reset off
        else if (wait_first_access && any_access) port_arst_any_r <= 0;
        else if (arst_r[2] && !arst_r[1])         port_arst_any_r <= wait_first_access;
    end

309
    always @(posedge aclk) begin
310 311 312 313 314
        if      (arst)            hba_reset_cntr <= 0; // 1; no HBA reset at arst
        else if (set_hba_rst)     hba_reset_cntr <= {HBA_RESET_BITS{1'b1}};
        else if (|hba_reset_cntr) hba_reset_cntr <= hba_reset_cntr - 1;
        
        hba_rst_r <= hba_reset_cntr != 0;
315
        
316 317
        if      (arst)         port_rst_r <= 0;
        else if (set_port_rst) port_rst_r <= ahci_regs_di[0]; // write "1" - reset on, write 0 - reset off
318
        
319 320 321 322 323
        if (arst || port_rst_on) was_hba_rst_aclk <= 0;
        else if (set_hba_rst)    was_hba_rst_aclk <= 1;
        
        if (arst || set_hba_rst) was_port_rst_aclk <= 0;
        else if (port_rst_on)    was_port_rst_aclk <= 1;
Andrey Filippov's avatar
Andrey Filippov committed
324 325 326
        
        if (arst) arst_r <= ~0;
        else      arst_r <= arst_r << 1;
327

328 329
    end

330 331
////    always @ (hba_clk) begin
    always @ (posedge aclk) begin
332 333
        was_hba_rst_r <= {was_hba_rst_aclk, was_hba_rst_r[2:1]};
        was_port_rst_r <= {was_port_rst_aclk, was_port_rst_r[2:1]};
334
    end
335 336
    

337

338 339 340 341 342
    always @(posedge aclk) begin
        if      (arst)             {afi_wcache,afi_rcache}  <= 8'h33;
        else if (afi_cache_set_w)  {afi_wcache,afi_rcache}  <= ahci_regs_di[7:0];
    end    

343 344 345 346 347
    always @(posedge aclk) begin
        if (arst) {pgm_wa,pgm_wd}  <= 0;
        else      {pgm_wa,pgm_wd}  <= {2{pgm_fsm_set_w}} & {pgm_fsm_and_w, ~pgm_fsm_and_w};
        
        if (pgm_fsm_set_w) pgm_ad <= ahci_regs_di[17:0];
348 349
    end
    
350 351


352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
/*
Will generate async reset on both HBA reset(for some time) and port reset (until released) 
until it is more clear about GTX reset options. Such reset will be applied to both PLL and GTX,
sata_phy_rst_out will be released after the sata clock is stable
    output                    soft_arst,        // reset SATA PHY not relying on SATA clock
                                                // TODO: Decode from {bram_addr, ahci_regs_di}, bram_wen_d
    input                     sata_phy_rst_out,  // when PLL locked, SATA PHY reset is over, this signal is released
    localparam GHC__GHC__HR__ADDR = 'h1;
    localparam GHC__GHC__HR__MASK = 'h1;
    localparam GHC__GHC__HR__DFLT = 'h0;
    
    reg [HBA_RESET_BITS-1:0] hba_reset_cntr; // time to keep hba_reset_r active after writing to GHC.HR
    reg                      hba_rst_r;      // hba reset (currently does ~ the same as port reset)
    reg                      port_rst_r;     // port reset by software
        .rst        (1'b0),                              // input
        .rrst       (hba_rst),                           // input
        .wrst       (arst),                              // input
        .rclk       (hba_clk),                           // input
        .wclk       (aclk),                              // input
        .we         (bram_wen_r && !high_sel),           // input
        .re         (soft_write_en),                     // input
        .data_in    ({bram_addr, ahci_regs_di}),         // input[15:0] 
        .data_out   ({soft_write_addr,soft_write_data}), // output[15:0] 
        .nempty     (soft_write_en),                     // output
        .half_empty ()                                   // output
 
// RO: Device Detection Initialization
    localparam HBA_PORT__PxSCTL__DET__ADDR = 'h4b;
    localparam HBA_PORT__PxSCTL__DET__MASK = 'hf;
    localparam HBA_PORT__PxSCTL__DET__DFLT = 'h0;
    

*/


387
    axibram_write #(
388
        .ADDRESS_BITS(AXIBRAM_BITS) // in debug mode - 1 bit more than ADDERSS_BITS
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
    ) axibram_write_i (
        .aclk        (aclk),                     // input
        .arst        (arst),                     // input
        .awaddr      (awaddr),                   // input[31:0] 
        .awvalid     (awvalid),                  // input
        .awready     (awready),                  // output
        .awid        (awid),                     // input[11:0] 
        .awlen       (awlen),                    // input[3:0] 
        .awsize      (awsize),                   // input[1:0] 
        .awburst     (awburst),                  // input[1:0] 
        .wdata       (wdata),                    // input[31:0] 
        .wvalid      (wvalid),                   // input
        .wready      (wready),                   // output
        .wid         (wid),                      // input[11:0] 
        .wlast       (wlast),                    // input
        .wstb        (wstb),                     // input[3:0] 
        .bvalid      (bvalid),                   // output
        .bready      (bready),                   // input
        .bid         (bid),                      // output[11:0] 
        .bresp       (bresp),                    // output[1:0] 
409
        .pre_awaddr  (), //pre_awaddr),          // output[9:0] 
410 411 412 413 414 415 416 417 418 419 420 421
        .start_burst (write_start_burst),        // output
//        .dev_ready   (!nowrite && !bram_ren[0]), // input
        .dev_ready   (!bram_wen),                // input   There will be no 2 bram_wen in a row
        .bram_wclk   (),                         // output
        .bram_waddr  (bram_waddr),               // output[9:0]
        .pre_bram_wen(pre_bram_wen),             // output
        .bram_wen    (bram_wen),                 // output
        .bram_wstb   (bram_wstb),                // output[3:0] 
        .bram_wdata  (bram_wdata)                // output[31:0] 
    );

    axibram_read #(
422
        .ADDRESS_BITS(AXIBRAM_BITS) // in debug mode - 1 bit more than ADDERSS_BITS
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
    ) axibram_read_i (
        .aclk        (aclk),                     // input
        .arst        (arst),                     // input
        .araddr      (araddr),                   // input[31:0] 
        .arvalid     (arvalid),                  // input
        .arready     (arready),                  // output
        .arid        (arid),                     // input[11:0] 
        .arlen       (arlen),                    // input[3:0] 
        .arsize      (arsize),                   // input[1:0] 
        .arburst     (arburst),                  // input[1:0] 
        .rdata       (rdata),                    // output[31:0] 
        .rvalid      (rvalid),                   // output reg 
        .rready      (rready),                   // input
        .rid         (rid),                      // output[11:0] reg 
        .rlast       (rlast),                    // output reg 
        .rresp       (rresp),                    // output[1:0] 
        .pre_araddr  (),                         // output[9:0] 
        .start_burst (),                         // output
        .dev_ready   (!write_busy_w),            // input
        .bram_rclk   (),                         // output
        .bram_raddr  (bram_raddr),               // output[9:0] 
        .bram_ren    (bram_ren[0]),              // output
        .bram_regen  (bram_ren[1]),              // output
446
`ifdef USE_DATASCOPE        
447 448 449
        .bram_rdata  ((datascope_sel[1] | datascope1_sel[1]) ?
                      (datascope1_sel[1]? datascope1_rdata : datascope_rdata) :
                       bram_rdata_r)              // input[31:0] 
450
`else
451
        .bram_rdata  (bram_rdata_r)              // input[31:0] 
452
`endif        
453 454
    );

455 456 457 458 459 460 461
    // Register memory, lower half uses read-modify-write using bit type from ahci_regs_type_i ROM, 2 aclk cycles/per write and
    // high addresses half are just plain write registers, they heve single-cycle write
    // Only low registers write generates cross-clock writes over the FIFO.
    // All registers can be accessed in byte/word/dword mode over the AXI
    
    // Lower registers are used as AHCI memory registers, high - for AHCI command list(s), to eliminate the need to update transfer count
    // in the system memory.
462

463
    ramt_var_wb_var_r #(
464 465 466 467 468
        .REGISTERS_A (0),
        .REGISTERS_B (1),
        .LOG2WIDTH_A (5),
        .LOG2WIDTH_B (5),
        .WRITE_MODE_A("NO_CHANGE"),
469 470
        .WRITE_MODE_B("NO_CHANGE")
        `include "includes/ahci_defaults.vh" 
471
    ) ahci_regs_i (
Andrey Filippov's avatar
Andrey Filippov committed
472 473
        .clk_a        (aclk),                                  // input
        .addr_a       (bram_addr),                             // input[9:0] 
Andrey Filippov's avatar
Andrey Filippov committed
474
        .en_a         (bram_ren[0] || bram_wen || bram_wen_r), // input
Andrey Filippov's avatar
Andrey Filippov committed
475
        .regen_a      (1'b0),                                  // input
Andrey Filippov's avatar
Andrey Filippov committed
476
        .we_a         (bram_wstb_r),                           // input[3:0]
477
//        
Andrey Filippov's avatar
Andrey Filippov committed
478 479 480 481 482 483 484 485 486
        .data_out_a   (bram_rdata),                            // output[31:0] 
        .data_in_a    (ahci_regs_di),                          // input[31:0] 
        .clk_b        (hba_clk),                               // input
        .addr_b       (hba_addr),                              // input[9:0] 
        .en_b         (hba_we || hba_re[0]),                   // input
        .regen_b      (hba_re[1]),                             // input
        .we_b         ({4{hba_we}}),                           // input
        .data_out_b   (hba_dout),                              // output[31:0] 
        .data_in_b    (hba_din)                                // input[31:0] 
487 488 489 490 491 492 493
    );

    ram_var_w_var_r #(
        .REGISTERS    (0),
        .LOG2WIDTH_WR (6),
        .LOG2WIDTH_RD (6),
        .DUMMY(0)
494
        `include "includes/ahci_types.vh" 
495
    ) ahci_regs_type_i (
496 497 498 499 500 501 502 503 504 505
        .rclk         (aclk),                       // input
        .raddr        (bram_addr[8:0]),             // input[8:0] 
        .ren          (bram_wen && !bram_addr[9]),  // input
        .regen        (1'b0),                       // input
        .data_out     (regbit_type),                // output[63:0] 
        .wclk         (1'b0),                       // input
        .waddr        (9'b0),                       // input[8:0] 
        .we           (1'b0),                       // input
        .web          (8'b0),                       // input[7:0] 
        .data_in      (64'b0)                       // input[63:0] 
506
    );
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    
`ifdef USE_DATASCOPE
        ram_var_w_var_r #(
            .REGISTERS    (0),
            .LOG2WIDTH_WR (5),
            .LOG2WIDTH_RD (5),
            .DUMMY(0)
        ) datascope_mem_i (
            .rclk         (aclk),                       // input
            .raddr        (bram_raddr[9:0]),            // input[9:0] 
            .ren          (bram_ren[0]),                // input
            .regen        (bram_ren[1]),                // input
            .data_out     (datascope_rdata),            // output[31:0] 
            .wclk         (datascope_clk),              // input
            .waddr        (datascope_waddr),            // input[9:0] 
            .we           (datascope_we),               // input
            .web          (8'hff),                      // input[7:0] 
            .data_in      (datascope_di)                // input[31:0] 
        );
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543

        ram_var_w_var_r #(
            .REGISTERS    (0),
            .LOG2WIDTH_WR (5),
            .LOG2WIDTH_RD (5),
            .DUMMY(0)
        ) datascope1_mem_i (
            .rclk         (aclk),                       // input
            .raddr        (bram_raddr[9:0]),            // input[9:0] 
            .ren          (bram_ren[0]),                // input
            .regen        (bram_ren[1]),                // input
            .data_out     (datascope1_rdata),           // output[31:0] 
            .wclk         (datascope1_clk),             // input
            .waddr        (datascope1_waddr),           // input[9:0] 
            .we           (datascope1_we),              // input
            .web          (8'hff),                      // input[7:0] 
            .data_in      (datascope1_di)               // input[31:0] 
        );
544
`endif
545 546 547 548 549 550 551 552 553 554

    fifo_cross_clocks #(
        .DATA_WIDTH(ADDRESS_BITS+32),
        .DATA_DEPTH(4)
    ) ahci_regs_set_i (
        .rst        (1'b0),                              // input
        .rrst       (hba_rst),                           // input
        .wrst       (arst),                              // input
        .rclk       (hba_clk),                           // input
        .wclk       (aclk),                              // input
555
        .we         (bram_wen_r && !high_sel),           // input
556 557 558 559 560 561 562
        .re         (soft_write_en),                     // input
        .data_in    ({bram_addr, ahci_regs_di}),         // input[15:0] 
        .data_out   ({soft_write_addr,soft_write_data}), // output[15:0] 
        .nempty     (soft_write_en),                     // output
        .half_empty ()                                   // output
    );

563 564 565 566 567 568 569 570 571 572
    pulse_cross_clock #(
        .EXTRA_DLY(0)
    ) afi_cache_set_i (
        .rst       (arst),             // input
        .src_clk   (aclk),             // input
        .dst_clk   (hba_clk),          // input
        .in_pulse  (afi_cache_set_w),  // input
        .out_pulse (afi_cache_set),    // output
        .busy()                        // output
    );
573 574 575 576


endmodule