axi_ahci_regs.v 23.2 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
Andrey Filippov's avatar
Andrey Filippov committed
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 117
    output                    afi_cache_set,
    output                    was_hba_rst,    // last reset was hba reset (not counting system reset)
    output                    was_port_rst    // last reset was port reset
118
);
119 120 121 122 123 124 125 126 127 128

`include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams
/*
    localparam GHC__GHC__HR__ADDR = 'h1;
    localparam GHC__GHC__HR__MASK = 'h1;
    localparam GHC__GHC__HR__DFLT = 'h0;
// 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;
129 130 131 132 133 134 135 136
// RW: SAXIHP write channel cache mode 
    localparam HBA_PORT__AFI_CACHE__WR_CM__ADDR = 'h5c;
    localparam HBA_PORT__AFI_CACHE__WR_CM__MASK = 'hf0;
    localparam HBA_PORT__AFI_CACHE__WR_CM__DFLT = 'h30;
// RW: SAXIHP read channel cache mode 
    localparam HBA_PORT__AFI_CACHE__RD_CM__ADDR = 'h5c;
    localparam HBA_PORT__AFI_CACHE__RD_CM__MASK = 'hf;
    localparam HBA_PORT__AFI_CACHE__RD_CM__DFLT = 'h3;
137 138
    
*/
139
    wire   [ADDRESS_BITS-1:0] bram_waddr;
140
//    wire   [ADDRESS_BITS-1:0] pre_awaddr;
141 142 143 144 145 146 147 148 149
    wire   [ADDRESS_BITS-1:0] bram_raddr;
    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; 
   

150 151 152
    wire             [1:0] bram_ren;
    reg                    write_busy_r;
    wire                   write_start_burst;
153
//    wire         nowrite;          // delay write in read-modify-write register accesses
Andrey Filippov's avatar
Andrey Filippov committed
154 155
///    wire                   write_busy_w = write_busy_r || write_start_burst;
    wire                   write_busy_w = write_busy_r || write_start_burst || bram_wen_r;
156 157 158 159 160 161 162 163 164 165
    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;
166
    
Andrey Filippov's avatar
Andrey Filippov committed
167
    reg [HBA_RESET_BITS-1:0] hba_reset_cntr; // time to keep hba_reset_r active after writing to GHC.HR
168 169
    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
170
    reg                      port_arst_any_r = 1;   // port _reset by software or POR
171
    
172
    wire                   high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write
173
    wire                   afi_cache_set_w = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__AFI_CACHE__WR_CM__ADDR);
174 175
    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);
176
    
177 178 179 180 181 182 183 184
    wire                   set_hba_rst =  bram_wen_r && !high_sel && (bram_addr == GHC__GHC__HR__ADDR) && (ahci_regs_di & GHC__GHC__HR__MASK);
    wire                   set_port_rst = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__PxSCTL__DET__ADDR) &&
                                          ((ahci_regs_di & HBA_PORT__PxSCTL__DET__MASK | 1) == HBA_PORT__PxSCTL__DET__MASK); // writing only 0/1
                                                                 //  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
185 186 187 188 189
    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];
190

Andrey Filippov's avatar
Andrey Filippov committed
191
    assign bram_addr =     bram_ren[0] ? bram_raddr : (bram_wen_r ? bram_waddr_r : bram_waddr);
Andrey Filippov's avatar
Andrey Filippov committed
192
    
Andrey Filippov's avatar
Andrey Filippov committed
193 194 195 196 197
    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];
198 199
    
    
200
    always @(posedge aclk) begin
Andrey Filippov's avatar
Andrey Filippov committed
201
///        bram_ren0_r <= bram_ren_w[0];
Andrey Filippov's avatar
Andrey Filippov committed
202
       
203 204 205 206 207 208
        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;
        
Andrey Filippov's avatar
Andrey Filippov committed
209
///        if (bram_ren_w[1])          bram_rdata_r <= bram_rdata;
210
        if (bram_ren[1])            bram_rdata_r <= bram_rdata;
211 212 213 214 215 216 217
        
        bram_wstb_r <= {4{bram_wen}} & bram_wstb;
        
        bram_wen_r <= bram_wen;
        
        if (bram_wen) bram_waddr_r <= bram_waddr;
        
218 219 220 221 222
    end

    generate
        genvar i;
        for (i=0; i < 32; i=i+1) begin: bit_type_block
223
            assign ahci_regs_di[i] = (regbit_type[2*i+1] && wmask[i] && !high_sel)?
224 225 226
                                       ((regbit_type[2*i] && wmask[i])?
                                          (bram_rdata[i] || bram_wdata_r[i]):   // 3: RW1
                                          (bram_rdata[i] && !bram_wdata_r[i])): // 2: RWC
227 228
                                       (((regbit_type[2*i] && wmask[i]) || high_sel)?
                                          (bram_wdata_r[i]):                    // 1: RW write new data - get here for high_sel
229 230 231 232
                                          (bram_rdata[i]));                     // 0: R0 (keep old data)
        end
    endgenerate    

Andrey Filippov's avatar
Andrey Filippov committed
233 234 235 236 237 238 239 240 241 242 243
//    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

244
    always @(posedge aclk) begin
245 246 247 248 249
        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;
250
        
251 252
        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
253
        
254 255 256 257 258
        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
259 260 261
        
        if (arst) arst_r <= ~0;
        else      arst_r <= arst_r << 1;
262

263 264 265 266 267
    end

    always @ (hba_clk) begin
        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]};
268
    end
269 270
    

271

272 273 274 275 276
    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    

277 278 279 280 281 282 283 284
    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];
    end    


285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
/*
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;
    

*/


320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
    axibram_write #(
        .ADDRESS_BITS(ADDRESS_BITS)
    ) 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] 
342
        .pre_awaddr  (), //pre_awaddr),          // output[9:0] 
343 344 345 346 347 348 349 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
        .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 #(
        .ADDRESS_BITS(ADDRESS_BITS)
    ) 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
        .bram_rdata  (bram_rdata_r)              // input[31:0] 
    );

382 383 384 385 386 387 388
    // 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.
389

390
    ramt_var_wb_var_r #(
391 392 393 394 395
        .REGISTERS_A (0),
        .REGISTERS_B (1),
        .LOG2WIDTH_A (5),
        .LOG2WIDTH_B (5),
        .WRITE_MODE_A("NO_CHANGE"),
396 397
        .WRITE_MODE_B("NO_CHANGE")
        `include "includes/ahci_defaults.vh" 
398
    ) ahci_regs_i (
Andrey Filippov's avatar
Andrey Filippov committed
399 400 401
        .clk_a        (aclk),                                  // input
        .addr_a       (bram_addr),                             // input[9:0] 
///        .en_a         (bram_ren[0] || write_busy_w),           // input
Andrey Filippov's avatar
Andrey Filippov committed
402 403
        .en_a         (bram_ren[0] || bram_wen || bram_wen_r), // input
///     .en_a         (bram_ren_w[0] || bram_wen || bram_wen_r), // input
Andrey Filippov's avatar
Andrey Filippov committed
404 405 406
        .regen_a      (1'b0),                                  // input
//        .we_a         (write_busy_r && !nowrite),            // input
        .we_a         (bram_wstb_r), //bram_wen_d),            // input[3:0]
407
//        
Andrey Filippov's avatar
Andrey Filippov committed
408 409 410 411 412 413 414 415 416
        .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] 
417 418 419 420 421 422 423
    );

    ram_var_w_var_r #(
        .REGISTERS    (0),
        .LOG2WIDTH_WR (6),
        .LOG2WIDTH_RD (6),
        .DUMMY(0)
424
        `include "includes/ahci_types.vh" 
425
    ) ahci_regs_type_i (
426 427 428 429 430 431 432 433 434 435
        .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] 
436 437 438 439 440 441 442 443 444 445 446
    );

    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
447
        .we         (bram_wen_r && !high_sel),           // input
448 449 450 451 452 453 454
        .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
    );

455 456 457 458 459 460 461 462 463 464
    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
    );
465 466 467 468


endmodule