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