Project Full coverage report
Current view: Cores-VeeR-EL2—Cores-VeeR-EL2—design—lib—axi4_to_ahb.sv Coverage Hit Total
Test Date: 14-11-2024 Toggle 79.1% 87 110
Test: all Branch 77.7% 101 130

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : // Copyright 2020 Western Digital Corporation or its affiliates.
       3              : //
       4              : // Licensed under the Apache License, Version 2.0 (the "License");
       5              : // you may not use this file except in compliance with the License.
       6              : // You may obtain a copy of the License at
       7              : //
       8              : // http://www.apache.org/licenses/LICENSE-2.0
       9              : //
      10              : // Unless required by applicable law or agreed to in writing, software
      11              : // distributed under the License is distributed on an "AS IS" BASIS,
      12              : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13              : // See the License for the specific language governing permissions and
      14              : // limitations under the License.
      15              : 
      16              : //********************************************************************************
      17              : // $Id$
      18              : //
      19              : // Owner:
      20              : // Function: AXI4 -> AHB Bridge
      21              : // Comments:
      22              : //
      23              : //********************************************************************************
      24              : module axi4_to_ahb
      25              : import el2_pkg::*;
      26              : #(
      27              : `include "el2_param.vh"
      28              : ,parameter TAG  = 1) (
      29              : 
      30     28468891 :    input                   clk,
      31     28468891 :    input                   free_clk,
      32           23 :    input                   rst_l,
      33              :    // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
      34              :    /*verilator coverage_off*/
      35              :    input                   scan_mode,
      36              :    /*verilator coverage_on*/
      37           23 :    input                   bus_clk_en,
      38            0 :    input                   clk_override,
      39            0 :    input                   dec_tlu_force_halt,
      40              : 
      41              :    // AXI signals
      42              :    // AXI Write Channels
      43          106 :    input  logic            axi_awvalid,
      44          343 :    output logic            axi_awready,
      45           50 :    input  logic [TAG-1:0]  axi_awid,
      46            2 :    input  logic [31:0]     axi_awaddr,
      47            0 :    input  logic [2:0]      axi_awsize,
      48            0 :    input  logic [2:0]      axi_awprot,
      49              : 
      50          106 :    input  logic            axi_wvalid,
      51          241 :    output logic            axi_wready,
      52            4 :    input  logic [63:0]     axi_wdata,
      53          310 :    input  logic [7:0]      axi_wstrb,
      54          122 :    input  logic            axi_wlast,
      55              : 
      56          224 :    output logic            axi_bvalid,
      57          122 :    input  logic            axi_bready,
      58            0 :    output logic [1:0]      axi_bresp,
      59           27 :    output logic [TAG-1:0]  axi_bid,
      60              : 
      61              :    // AXI Read Channels
      62          110 :    input  logic            axi_arvalid,
      63          241 :    output logic            axi_arready,
      64            0 :    input  logic [TAG-1:0]  axi_arid,
      65            2 :    input  logic [31:0]     axi_araddr,
      66            0 :    input  logic [2:0]      axi_arsize,
      67            0 :    input  logic [2:0]      axi_arprot,
      68              : 
      69          122 :    output logic            axi_rvalid,
      70          110 :    input  logic            axi_rready,
      71           27 :    output logic [TAG-1:0]  axi_rid,
      72            6 :    output logic [63:0]     axi_rdata,
      73            0 :    output logic [1:0]      axi_rresp,
      74           23 :    output logic            axi_rlast,
      75              : 
      76              :    // AHB-Lite signals
      77            2 :    output logic [31:0]     ahb_haddr,       // ahb bus address
      78              :    /* exclude signals that are tied to constant value in this file */
      79              :    /*verilator coverage_off*/
      80              :    output logic [2:0]      ahb_hburst,      // tied to 0
      81              :    output logic            ahb_hmastlock,   // tied to 0
      82              :    /*verilator coverage_on*/
      83            0 :    output logic [3:0]      ahb_hprot,       // [3:1] are tied to 3'b001
      84            0 :    output logic [2:0]      ahb_hsize,       // size of bus transaction (possible values 0,1,2,3)
      85         1198 :    output logic [1:0]      ahb_htrans,      // Transaction type (possible values 0,2 only right now)
      86          135 :    output logic            ahb_hwrite,      // ahb bus write
      87            7 :    output logic [63:0]     ahb_hwdata,      // ahb bus write data
      88              : 
      89            6 :    input logic [63:0]      ahb_hrdata,      // ahb bus read data
      90          194 :    input logic             ahb_hready,      // slave ready to accept transaction
      91            0 :    input logic             ahb_hresp        // slave response (high indicates erro)
      92              : 
      93              : );
      94              : 
      95              :    localparam ID   = 1;
      96              :    localparam PRTY = 1;
      97              :    typedef enum logic [3:0] {
      98              :         IDLE            = 4'b0000,
      99              :         CMD_RD          = 4'b0001,
     100              :         CMD_WR          = 4'b1001,
     101              :         DATA_RD         = 4'b0010,
     102              :         DATA_WR         = 4'b1010,
     103              :         DONE_RD         = 4'b0011,
     104              :         DONE_WR         = 4'b1011,
     105              :         STREAM_RD       = 4'b0101,
     106              :         STREAM_ERR_RD   = 4'b0110
     107              :     } state_t;
     108              : 
     109          212 :    state_t buf_state, buf_nxtstate;
     110              : 
     111          234 :    logic             slave_valid;
     112           27 :    logic [TAG-1:0]   slave_tag;
     113            6 :    logic [63:0]      slave_rdata;
     114          135 :    logic [3:0]       slave_opc;
     115              : 
     116          106 :    logic             wrbuf_en, wrbuf_data_en;
     117          224 :    logic             wrbuf_cmd_sent, wrbuf_rst;
     118          224 :    logic             wrbuf_vld;
     119          224 :    logic             wrbuf_data_vld;
     120           23 :    logic [TAG-1:0]   wrbuf_tag;
     121            0 :    logic [2:0]       wrbuf_size;
     122            2 :    logic [31:0]      wrbuf_addr;
     123           30 :    logic [63:0]      wrbuf_data;
     124           59 :    logic [7:0]       wrbuf_byteen;
     125              : 
     126          216 :    logic             master_valid;
     127          241 :    logic             master_ready;
     128           50 :    logic [TAG-1:0]   master_tag;
     129            2 :    logic [31:0]      master_addr;
     130           30 :    logic [63:0]      master_wdata;
     131            0 :    logic [2:0]       master_size;
     132            0 :    logic [2:0]       master_opc;
     133           59 :    logic [7:0]       master_byteen;
     134              : 
     135              :    // Buffer signals (one entry buffer)
     136            2 :    logic [31:0]                buf_addr;
     137            6 :    logic [1:0]                 buf_size;
     138          135 :    logic                       buf_write;
     139           59 :    logic [7:0]                 buf_byteen;
     140            5 :    logic                       buf_aligned;
     141            7 :    logic [63:0]                buf_data;
     142           27 :    logic [TAG-1:0]             buf_tag;
     143              : 
     144              :    //Miscellaneous signals
     145            0 :    logic                       buf_rst;
     146           50 :    logic [TAG-1:0]             buf_tag_in;
     147            2 :    logic [31:0]                buf_addr_in;
     148           59 :    logic [7:0]                 buf_byteen_in;
     149            7 :    logic [63:0]                buf_data_in;
     150          224 :    logic                       buf_write_in;
     151           23 :    logic                       buf_aligned_in;
     152            0 :    logic [2:0]                 buf_size_in;
     153              : 
     154          522 :    logic                       buf_state_en;
     155          216 :    logic                       buf_wr_en;
     156          216 :    logic                       buf_data_wr_en;
     157          216 :    logic                       slvbuf_error_en;
     158          224 :    logic                       wr_cmd_vld;
     159              : 
     160         1198 :    logic                       cmd_done_rst, cmd_done, cmd_doneQ;
     161          224 :    logic                       trxn_done;
     162            0 :    logic [2:0]                 buf_cmd_byte_ptr, buf_cmd_byte_ptrQ, buf_cmd_nxtbyte_ptr;
     163          318 :    logic                       buf_cmd_byte_ptr_en;
     164            0 :    logic                       found;
     165              : 
     166          234 :    logic                       slave_valid_pre;
     167          194 :    logic                       ahb_hready_q;
     168            0 :    logic                       ahb_hresp_q;
     169         1198 :    logic [1:0]                 ahb_htrans_q;
     170          135 :    logic                       ahb_hwrite_q;
     171            6 :    logic [63:0]                ahb_hrdata_q;
     172              : 
     173              : 
     174          135 :    logic                       slvbuf_write;
     175            0 :    logic                       slvbuf_error;
     176           27 :    logic [TAG-1:0]             slvbuf_tag;
     177              : 
     178            0 :    logic                       slvbuf_error_in;
     179          234 :    logic                       slvbuf_wr_en;
     180          216 :    logic                       bypass_en;
     181          110 :    logic                       rd_bypass_idle;
     182              : 
     183          224 :    logic                       last_addr_en;
     184            2 :    logic [31:0]                last_bus_addr;
     185              : 
     186              :    // Clocks
     187          426 :    logic                       buf_clken;
     188          216 :    logic                       ahbm_data_clken;
     189              : 
     190          474 :    logic                       buf_clk;
     191         4143 :    logic                       bus_clk;
     192         1490 :    logic                       ahbm_data_clk;
     193              : 
     194            0 :    logic                       dec_tlu_force_halt_bus, dec_tlu_force_halt_bus_ns, dec_tlu_force_halt_bus_q;
     195              : 
     196              :    // Function to get the length from byte enable
     197          306 :    function automatic logic [1:0] get_write_size;
     198              :       input logic [7:0] byteen;
     199              : 
     200              :       logic [1:0]       size;
     201              : 
     202          306 :       size[1:0] = (2'b11 & {2{(byteen[7:0] == 8'hff)}}) |
     203          306 :                   (2'b10 & {2{((byteen[7:0] == 8'hf0) | (byteen[7:0] == 8'h0f))}}) |
     204          306 :                   (2'b01 & {2{((byteen[7:0] == 8'hc0) | (byteen[7:0] == 8'h30) | (byteen[7:0] == 8'h0c) | (byteen[7:0] == 8'h03))}});
     205              : 
     206          306 :       return size[1:0];
     207              :    endfunction // get_write_size
     208              : 
     209              :    // Function to get the length from byte enable
     210          343 :    function automatic logic [2:0] get_write_addr;
     211              :       input logic [7:0] byteen;
     212              : 
     213              :       logic [2:0]       addr;
     214              : 
     215          343 :       addr[2:0] = (3'h0 & {3{((byteen[7:0] == 8'hff) | (byteen[7:0] == 8'h0f) | (byteen[7:0] == 8'h03))}}) |
     216          343 :                   (3'h2 & {3{(byteen[7:0] == 8'h0c)}})                                                     |
     217          343 :                   (3'h4 & {3{((byteen[7:0] == 8'hf0) | (byteen[7:0] == 8'h03))}})                          |
     218          343 :                   (3'h6 & {3{(byteen[7:0] == 8'hc0)}});
     219              : 
     220          343 :       return addr[2:0];
     221              :    endfunction // get_write_addr
     222              : 
     223              :    // Function to get the next byte pointer
     224         2217 :    function automatic logic [2:0] get_nxtbyte_ptr (logic [2:0] current_byte_ptr, logic [7:0] byteen, logic get_next);
     225              :       logic [2:0] start_ptr;
     226              :       logic       found;
     227         2217 :       found = '0;
     228         2217 :       get_nxtbyte_ptr[2:0] = 3'd0; 
     229         2217 :       start_ptr[2:0] = get_next ? (current_byte_ptr[2:0] + 3'b1) : current_byte_ptr[2:0];
     230         3771 :       for (int j=0; j<8; j++) begin
     231         4977 :          if (~found) begin
     232         5085 :             get_nxtbyte_ptr[2:0] = 3'(j);
     233         5085 :             found |= (byteen[j] & (3'(j) >= start_ptr[2:0])) ;
     234              :          end
     235              :       end
     236              :    endfunction // get_nextbyte_ptr
     237              : 
     238              :    // Create bus synchronized version of force halt
     239              :    assign dec_tlu_force_halt_bus = dec_tlu_force_halt | dec_tlu_force_halt_bus_q;
     240              :    assign dec_tlu_force_halt_bus_ns = ~bus_clk_en & dec_tlu_force_halt_bus;
     241              :    rvdff  #(.WIDTH(1))   force_halt_busff(.din(dec_tlu_force_halt_bus_ns), .dout(dec_tlu_force_halt_bus_q), .clk(free_clk), .*);
     242              : 
     243              :    // Write buffer
     244              :    assign wrbuf_en       = axi_awvalid & axi_awready & master_ready;
     245              :    assign wrbuf_data_en  = axi_wvalid & axi_wready & master_ready;
     246              :    assign wrbuf_cmd_sent = master_valid & master_ready & (master_opc[2:1] == 2'b01);
     247              :    assign wrbuf_rst      = (wrbuf_cmd_sent & ~wrbuf_en) | dec_tlu_force_halt_bus;
     248              : 
     249              :    assign axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready;
     250              :    assign axi_wready  = ~(wrbuf_data_vld & ~wrbuf_cmd_sent) & master_ready;
     251              :    assign axi_arready = ~(wrbuf_vld & wrbuf_data_vld) & master_ready;
     252              :    assign axi_rlast   = 1'b1;
     253              : 
     254              :    assign wr_cmd_vld          = (wrbuf_vld & wrbuf_data_vld);
     255              :    assign master_valid        = wr_cmd_vld | axi_arvalid;
     256              :    assign master_tag[TAG-1:0] = wr_cmd_vld ? wrbuf_tag[TAG-1:0] : axi_arid[TAG-1:0];
     257              :    assign master_opc[2:0]     = wr_cmd_vld ? 3'b011 : 3'b0;
     258              :    assign master_addr[31:0]   = wr_cmd_vld ? wrbuf_addr[31:0] : axi_araddr[31:0];
     259              :    assign master_size[2:0]    = wr_cmd_vld ? wrbuf_size[2:0] : axi_arsize[2:0];
     260              :    assign master_byteen[7:0]  = wrbuf_byteen[7:0];
     261              :    assign master_wdata[63:0]  = wrbuf_data[63:0];
     262              : 
     263              :    // AXI response channel signals
     264              :    assign axi_bvalid       = slave_valid & slave_opc[3];
     265              :    assign axi_bresp[1:0]   = slave_opc[0] ? 2'b10 : (slave_opc[1] ? 2'b11 : 2'b0);
     266              :    assign axi_bid[TAG-1:0] = slave_tag[TAG-1:0];
     267              : 
     268              :    assign axi_rvalid       = slave_valid & (slave_opc[3:2] == 2'b0);
     269              :    assign axi_rresp[1:0]   = slave_opc[0] ? 2'b10 : (slave_opc[1] ? 2'b11 : 2'b0);
     270              :    assign axi_rid[TAG-1:0] = slave_tag[TAG-1:0];
     271              :    assign axi_rdata[63:0]  = slave_rdata[63:0];
     272              : 
     273              :  // FIFO state machine
     274           23 :    always_comb begin
     275           23 :       buf_nxtstate   = IDLE;
     276           23 :       buf_state_en   = 1'b0;
     277           23 :       buf_wr_en      = 1'b0;
     278           23 :       buf_data_wr_en = 1'b0;
     279           23 :       slvbuf_error_in   = 1'b0;
     280           23 :       slvbuf_error_en   = 1'b0;
     281           23 :       buf_write_in   = 1'b0;
     282           23 :       cmd_done       = 1'b0;
     283           23 :       trxn_done      = 1'b0;
     284           23 :       buf_cmd_byte_ptr_en = 1'b0;
     285           23 :       buf_cmd_byte_ptr[2:0] = '0;
     286           23 :       slave_valid_pre   = 1'b0;
     287           23 :       master_ready   = 1'b0;
     288           23 :       ahb_htrans[1:0]  = 2'b0;
     289           23 :       slvbuf_wr_en     = 1'b0;
     290           23 :       bypass_en        = 1'b0;
     291           23 :       rd_bypass_idle   = 1'b0;
     292              : 
     293           23 :       case (buf_state)
     294      8870595 :          IDLE: begin
     295      8870595 :                   master_ready   = 1'b1;
     296      8870595 :                   buf_write_in = (master_opc[2:1] == 2'b01);
     297      8870595 :                   buf_nxtstate = buf_write_in ? CMD_WR : CMD_RD;
     298      8870595 :                   buf_state_en = master_valid & master_ready;
     299      8870595 :                   buf_wr_en    = buf_state_en;
     300      8870595 :                   buf_data_wr_en = buf_state_en & (buf_nxtstate == CMD_WR);
     301      8870595 :                   buf_cmd_byte_ptr_en   = buf_state_en;
     302      8870595 :                   buf_cmd_byte_ptr[2:0] = buf_write_in ? get_nxtbyte_ptr(3'b0,buf_byteen_in[7:0],1'b0) : master_addr[2:0];
     303      8870595 :                   bypass_en       = buf_state_en;
     304      8870595 :                   rd_bypass_idle  = bypass_en & (buf_nxtstate == CMD_RD);
     305      8870595 :                   ahb_htrans[1:0] = {2{bypass_en}} & 2'b10;
     306              :           end
     307         1900 :          CMD_RD: begin
     308         1900 :                   buf_nxtstate    = (master_valid & (master_opc[2:0] == 3'b000))? STREAM_RD : DATA_RD;
     309         1900 :                   buf_state_en    = ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) & ~ahb_hwrite_q;
     310         1900 :                   cmd_done        = buf_state_en & ~master_valid;
     311         1900 :                   slvbuf_wr_en    = buf_state_en;
     312         1900 :                   master_ready  = buf_state_en & (buf_nxtstate == STREAM_RD);
     313         1900 :                   buf_wr_en       = master_ready;
     314         1900 :                   bypass_en       = master_ready & master_valid;
     315         1900 :                   buf_cmd_byte_ptr[2:0] = bypass_en ? master_addr[2:0] : buf_addr[2:0];
     316         1900 :                   ahb_htrans[1:0] = 2'b10 & {2{~buf_state_en | bypass_en}};
     317              :          end
     318            0 :          STREAM_RD: begin
     319            0 :                   master_ready  =  (ahb_hready_q & ~ahb_hresp_q) & ~(master_valid & master_opc[2:1] == 2'b01);
     320            0 :                   buf_wr_en       = (master_valid & master_ready & (master_opc[2:0] == 3'b000)); // update the fifo if we are streaming the read commands
     321            0 :                   buf_nxtstate    = ahb_hresp_q ? STREAM_ERR_RD : (buf_wr_en ? STREAM_RD : DATA_RD);            // assuming that the master accpets the slave response right away.
     322            0 :                   buf_state_en    = (ahb_hready_q | ahb_hresp_q);
     323            0 :                   buf_data_wr_en  = buf_state_en;
     324            0 :                   slvbuf_error_in = ahb_hresp_q;
     325            0 :                   slvbuf_error_en = buf_state_en;
     326            0 :                   slave_valid_pre  = buf_state_en & ~ahb_hresp_q;             // send a response right away if we are not going through an error response.
     327            0 :                   cmd_done        = buf_state_en & ~master_valid;                     // last one of the stream should not send a htrans
     328            0 :                   bypass_en       = master_ready & master_valid & (buf_nxtstate == STREAM_RD) & buf_state_en;
     329            0 :                   buf_cmd_byte_ptr[2:0] = bypass_en ? master_addr[2:0] : buf_addr[2:0];
     330            0 :                   ahb_htrans[1:0] = 2'b10 & {2{~((buf_nxtstate != STREAM_RD) & buf_state_en)}};
     331            0 :                   slvbuf_wr_en    = buf_wr_en;                                         // shifting the contents from the buf to slv_buf for streaming cases
     332              :          end // case: STREAM_RD
     333            0 :          STREAM_ERR_RD: begin
     334            0 :                   buf_nxtstate = DATA_RD;
     335            0 :                   buf_state_en = ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) & ~ahb_hwrite_q;
     336            0 :                   slave_valid_pre = buf_state_en;
     337            0 :                   slvbuf_wr_en   = buf_state_en;     // Overwrite slvbuf with buffer
     338            0 :                   buf_cmd_byte_ptr[2:0] = buf_addr[2:0];
     339            0 :                   ahb_htrans[1:0] = 2'b10 & {2{~buf_state_en}};
     340              :          end
     341          280 :          DATA_RD: begin
     342          280 :                   buf_nxtstate   = DONE_RD;
     343          280 :                   buf_state_en   = (ahb_hready_q | ahb_hresp_q);
     344          280 :                   buf_data_wr_en = buf_state_en;
     345          280 :                   slvbuf_error_in= ahb_hresp_q;
     346          280 :                   slvbuf_error_en= buf_state_en;
     347          280 :                   slvbuf_wr_en   = buf_state_en;
     348              : 
     349              :          end
     350          961 :          CMD_WR: begin
     351          961 :                   buf_nxtstate = DATA_WR;
     352          961 :                   trxn_done    = ahb_hready_q & ahb_hwrite_q & (ahb_htrans_q[1:0] != 2'b0);
     353          961 :                   buf_state_en = trxn_done;
     354          961 :                   buf_cmd_byte_ptr_en = buf_state_en;
     355          961 :                   slvbuf_wr_en    = buf_state_en;
     356          961 :                   buf_cmd_byte_ptr    = trxn_done ? get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1) : buf_cmd_byte_ptrQ;
     357          961 :                   cmd_done            = trxn_done & (buf_aligned | (buf_cmd_byte_ptrQ == 3'b111) |
     358          961 :                                                      (buf_byteen[get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1)] == 1'b0));
     359          961 :                   ahb_htrans[1:0] = {2{~(cmd_done | cmd_doneQ)}} & 2'b10;
     360              :          end
     361          343 :          DATA_WR: begin
     362          343 :                   buf_state_en = (cmd_doneQ & ahb_hready_q) | ahb_hresp_q;
     363          343 :                   master_ready = buf_state_en & ~ahb_hresp_q & axi_bready;   // Ready to accept new command if current command done and no error
     364          343 :                   buf_nxtstate = (ahb_hresp_q | ~axi_bready) ? DONE_WR :
     365          343 :                                   ((master_valid & master_ready) ? ((master_opc[2:1] == 2'b01) ? CMD_WR : CMD_RD) : IDLE);
     366          343 :                   slvbuf_error_in = ahb_hresp_q;
     367          343 :                   slvbuf_error_en = buf_state_en;
     368              : 
     369          343 :                   buf_write_in = (master_opc[2:1] == 2'b01);
     370          343 :                   buf_wr_en = buf_state_en & ((buf_nxtstate == CMD_WR) | (buf_nxtstate == CMD_RD));
     371          343 :                   buf_data_wr_en = buf_wr_en;
     372              : 
     373          343 :                   cmd_done     = (ahb_hresp_q | (ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) &
     374          343 :                                  ((buf_cmd_byte_ptrQ == 3'b111) | (buf_byteen[get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1)] == 1'b0))));
     375          343 :                   bypass_en       = buf_state_en & buf_write_in & (buf_nxtstate == CMD_WR);   // Only bypass for writes for the time being
     376          343 :                   ahb_htrans[1:0] = {2{(~(cmd_done | cmd_doneQ) | bypass_en)}} & 2'b10;
     377          343 :                   slave_valid_pre  = buf_state_en & (buf_nxtstate != DONE_WR);
     378              : 
     379          343 :                   trxn_done = ahb_hready_q & ahb_hwrite_q & (ahb_htrans_q[1:0] != 2'b0);
     380          343 :                   buf_cmd_byte_ptr_en = trxn_done | bypass_en;
     381          343 :                   buf_cmd_byte_ptr = bypass_en ? get_nxtbyte_ptr(3'b0,buf_byteen_in[7:0],1'b0) :
     382          343 :                                                  trxn_done ? get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1) : buf_cmd_byte_ptrQ;
     383              :          end
     384            0 :          DONE_WR: begin
     385            0 :                   buf_nxtstate = IDLE;
     386            0 :                   buf_state_en = axi_bvalid & axi_bready;
     387            0 :                   slvbuf_error_en = 1'b1;
     388            0 :                   slave_valid_pre = 1'b1;
     389              :          end
     390         1090 :          DONE_RD: begin
     391         1090 :                   buf_nxtstate = IDLE;
     392         1090 :                   buf_state_en = axi_rvalid & axi_rready; // axi_rlast == 1
     393         1090 :                   slvbuf_error_en = 1'b1;
     394         1090 :                   slave_valid_pre = 1'b1;
     395              :          end
     396            0 :          default: begin
     397            0 :                   buf_nxtstate = IDLE;
     398            0 :                   buf_state_en = 1'b1;
     399              :          end
     400              :       endcase
     401              :    end
     402              : 
     403              :    assign buf_rst              = dec_tlu_force_halt_bus;
     404              :    assign cmd_done_rst         = slave_valid_pre;
     405              :    assign buf_addr_in[31:3]    = master_addr[31:3];
     406              :    assign buf_addr_in[2:0]     = (buf_aligned_in & (master_opc[2:1] == 2'b01)) ? get_write_addr(master_byteen[7:0]) : master_addr[2:0];
     407              :    assign buf_tag_in[TAG-1:0]  = master_tag[TAG-1:0];
     408              :    assign buf_byteen_in[7:0]   = wrbuf_byteen[7:0];
     409              :    assign buf_data_in[63:0]    = (buf_state == DATA_RD) ? ahb_hrdata_q[63:0] : master_wdata[63:0];
     410              :    assign buf_size_in[1:0]     = (buf_aligned_in & (master_size[1:0] == 2'b11) & (master_opc[2:1] == 2'b01)) ? get_write_size(master_byteen[7:0]) : master_size[1:0];
     411              :    assign buf_aligned_in       = (master_opc[2:0] == 3'b0)    |   // reads are always aligned since they are either DW or sideeffects
     412              :                                  (master_size[1:0] == 2'b0) |  (master_size[1:0] == 2'b01) | (master_size[1:0] == 2'b10) | // Always aligned for Byte/HW/Word since they can be only for non-idempotent. IFU/SB are always aligned
     413              :                                  ((master_size[1:0] == 2'b11) &
     414              :                                   ((master_byteen[7:0] == 8'h3)  | (master_byteen[7:0] == 8'hc)   | (master_byteen[7:0] == 8'h30) | (master_byteen[7:0] == 8'hc0) |
     415              :                                    (master_byteen[7:0] == 8'hf)  | (master_byteen[7:0] == 8'hf0)  | (master_byteen[7:0] == 8'hff)));
     416              : 
     417              :    // Generate the ahb signals
     418              :    assign ahb_haddr[31:3] = bypass_en ? master_addr[31:3]  : buf_addr[31:3];
     419              :    assign ahb_haddr[2:0]  = {3{(ahb_htrans == 2'b10)}} & buf_cmd_byte_ptr[2:0];    // Trxn should be aligned during IDLE
     420              :    assign ahb_hsize[2:0]  = bypass_en ? {1'b0, ({2{buf_aligned_in}} & buf_size_in[1:0])} :
     421              :                                         {1'b0, ({2{buf_aligned}} & buf_size[1:0])};   // Send the full size for aligned trxn
     422              :    assign ahb_hburst[2:0] = 3'b0;
     423              :    assign ahb_hmastlock   = 1'b0;
     424              :    assign ahb_hprot[3:0]  = {3'b001,~axi_arprot[2]};
     425              :    assign ahb_hwrite      = bypass_en ? (master_opc[2:1] == 2'b01) : buf_write;
     426              :    assign ahb_hwdata[63:0] = buf_data[63:0];
     427              : 
     428              :    assign slave_valid          = slave_valid_pre;// & (~slvbuf_posted_write | slvbuf_error);
     429              :    assign slave_opc[3:2]       = slvbuf_write ? 2'b11 : 2'b00;
     430              :    assign slave_opc[1:0]       = {2{slvbuf_error}} & 2'b10;
     431              :    assign slave_rdata[63:0]    = slvbuf_error ? {2{last_bus_addr[31:0]}} : ((buf_state == DONE_RD) ? buf_data[63:0] : ahb_hrdata_q[63:0]);
     432              :    assign slave_tag[TAG-1:0]   = slvbuf_tag[TAG-1:0];
     433              : 
     434              :    assign last_addr_en = (ahb_htrans[1:0] != 2'b0) & ahb_hready & ahb_hwrite ;
     435              : 
     436              : 
     437              :    rvdffsc_fpga #(.WIDTH(1))   wrbuf_vldff     (.din(1'b1),              .dout(wrbuf_vld),          .en(wrbuf_en),      .clear(wrbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     438              :    rvdffsc_fpga #(.WIDTH(1))   wrbuf_data_vldff(.din(1'b1),              .dout(wrbuf_data_vld),     .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     439              :    rvdffs_fpga  #(.WIDTH(TAG)) wrbuf_tagff     (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en),                         .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     440              :    rvdffs_fpga  #(.WIDTH(3))   wrbuf_sizeff    (.din(axi_awsize[2:0]),   .dout(wrbuf_size[2:0]),    .en(wrbuf_en),                         .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     441              :    rvdffe       #(.WIDTH(32))  wrbuf_addrff    (.din(axi_awaddr[31:0]),  .dout(wrbuf_addr[31:0]),   .en(wrbuf_en & bus_clk_en),            .clk(clk), .*);
     442              :    rvdffe       #(.WIDTH(64))  wrbuf_dataff    (.din(axi_wdata[63:0]),   .dout(wrbuf_data[63:0]),   .en(wrbuf_data_en & bus_clk_en),       .clk(clk), .*);
     443              :    rvdffs_fpga  #(.WIDTH(8))   wrbuf_byteenff  (.din(axi_wstrb[7:0]),    .dout(wrbuf_byteen[7:0]),  .en(wrbuf_data_en),                    .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     444              : 
     445              :    rvdffs_fpga #(.WIDTH(32))   last_bus_addrff (.din(ahb_haddr[31:0]),   .dout(last_bus_addr[31:0]), .en(last_addr_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     446              : 
     447              :    rvdffsc_fpga #(.WIDTH($bits(state_t))) buf_state_ff  (.din(buf_nxtstate),        .dout({buf_state}),      .en(buf_state_en), .clear(buf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     448              :    rvdffs_fpga #(.WIDTH(1))               buf_writeff   (.din(buf_write_in),        .dout(buf_write),        .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*);
     449              :    rvdffs_fpga #(.WIDTH(TAG))             buf_tagff     (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*);
     450              :    rvdffe      #(.WIDTH(32))              buf_addrff    (.din(buf_addr_in[31:0]),   .dout(buf_addr[31:0]),   .en(buf_wr_en & bus_clk_en),        .clk(clk), .*);
     451              :    rvdffs_fpga #(.WIDTH(2))               buf_sizeff    (.din(buf_size_in[1:0]),    .dout(buf_size[1:0]),    .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*);
     452              :    rvdffs_fpga #(.WIDTH(1))               buf_alignedff (.din(buf_aligned_in),      .dout(buf_aligned),      .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*);
     453              :    rvdffs_fpga #(.WIDTH(8))               buf_byteenff  (.din(buf_byteen_in[7:0]),  .dout(buf_byteen[7:0]),  .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*);
     454              :    rvdffe      #(.WIDTH(64))              buf_dataff    (.din(buf_data_in[63:0]),   .dout(buf_data[63:0]),   .en(buf_data_wr_en & bus_clk_en),   .clk(clk), .*);
     455              : 
     456              : 
     457              :    rvdffs_fpga #(.WIDTH(1))   slvbuf_writeff  (.din(buf_write),        .dout(slvbuf_write),        .en(slvbuf_wr_en),    .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*);
     458              :    rvdffs_fpga #(.WIDTH(TAG)) slvbuf_tagff    (.din(buf_tag[TAG-1:0]), .dout(slvbuf_tag[TAG-1:0]), .en(slvbuf_wr_en),    .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*);
     459              :    rvdffs_fpga #(.WIDTH(1))   slvbuf_errorff  (.din(slvbuf_error_in),  .dout(slvbuf_error),        .en(slvbuf_error_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     460              : 
     461              :    rvdffsc_fpga #(.WIDTH(1)) buf_cmd_doneff     (.din(1'b1),                  .dout(cmd_doneQ),              .en(cmd_done),            .clear(cmd_done_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     462              :    rvdffs_fpga #(.WIDTH(3))  buf_cmd_byte_ptrff (.din(buf_cmd_byte_ptr[2:0]), .dout(buf_cmd_byte_ptrQ[2:0]), .en(buf_cmd_byte_ptr_en),                       .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
     463              : 
     464              :    rvdff_fpga #(.WIDTH(1))  hready_ff (.din(ahb_hready),       .dout(ahb_hready_q),       .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*);
     465              :    rvdff_fpga #(.WIDTH(2))  htrans_ff (.din(ahb_htrans[1:0]),  .dout(ahb_htrans_q[1:0]),  .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*);
     466              :    rvdff_fpga #(.WIDTH(1))  hwrite_ff (.din(ahb_hwrite),       .dout(ahb_hwrite_q),       .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*);
     467              :    rvdff_fpga #(.WIDTH(1))  hresp_ff  (.din(ahb_hresp),        .dout(ahb_hresp_q),        .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*);
     468              :    rvdff_fpga #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_clk), .clken(ahbm_data_clken), .rawclk(clk), .*);
     469              : 
     470              :    // Clock headers
     471              :    // clock enables for ahbm addr/data
     472              :    assign buf_clken       = bus_clk_en & (buf_wr_en | slvbuf_wr_en | clk_override);
     473              :    assign ahbm_data_clken = bus_clk_en & ((buf_state != IDLE) | clk_override);
     474              : 
     475              : `ifdef RV_FPGA_OPTIMIZE
     476              :    assign bus_clk = 1'b0;
     477              :    assign buf_clk = 1'b0;
     478              :    assign ahbm_data_clk = 1'b0;
     479              : `else
     480              :    rvclkhdr bus_cgc       (.en(bus_clk_en),      .l1clk(bus_clk),       .*);
     481              :    rvclkhdr buf_cgc       (.en(buf_clken),       .l1clk(buf_clk), .*);
     482              :    rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*);
     483              : `endif
     484              : 
     485              : `ifdef RV_ASSERT_ON
     486              :    property ahb_trxn_aligned;
     487              :      @(posedge bus_clk) ahb_htrans[1]  |-> ((ahb_hsize[2:0] == 3'h0)                              |
     488              :                                         ((ahb_hsize[2:0] == 3'h1) & (ahb_haddr[0] == 1'b0))   |
     489              :                                         ((ahb_hsize[2:0] == 3'h2) & (ahb_haddr[1:0] == 2'b0)) |
     490              :                                         ((ahb_hsize[2:0] == 3'h3) & (ahb_haddr[2:0] == 3'b0)));
     491              :    endproperty
     492              :    assert_ahb_trxn_aligned: assert property (ahb_trxn_aligned) else
     493              :      $display("Assertion ahb_trxn_aligned failed: ahb_htrans=2'h%h, ahb_hsize=3'h%h, ahb_haddr=32'h%h",ahb_htrans[1:0], ahb_hsize[2:0], ahb_haddr[31:0]);
     494              : 
     495              :    property ahb_error_protocol;
     496              :       @(posedge bus_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp));
     497              :    endproperty
     498              :    assert_ahb_error_protocol: assert property (ahb_error_protocol) else
     499              :       $display("Bus Error with hReady isn't preceded with Bus Error without hready");
     500              : `endif
     501              : 
     502              : endmodule // axi4_to_ahb