../src/pulp-platform_riscv-dbg_0.1_0/pulp_riscv_dbg/src/dm_sba.sv Cov: 100%

   1: /* Copyright 2018 ETH Zurich and University of Bologna.
   2: * Copyright and related rights are licensed under the Solderpad Hardware
   3: * License, Version 0.51 (the “License”); you may not use this file except in
   4: * compliance with the License.  You may obtain a copy of the License at
   5: * http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
   6: * or agreed to in writing, software, hardware and materials distributed under
   7: * this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
   8: * CONDITIONS OF ANY KIND, either express or implied. See the License for the
   9: * specific language governing permissions and limitations under the License.
  10: *
  11: * File:   dm_sba.sv
  12: * Author: Florian Zaruba 
  13: * Date:   1.8.2018
  14: *
  15: * Description: System Bus Access Module
  16: *
  17: */
  18: module dm_sba #(
  19:   parameter int unsigned BusWidth = 32
  20: ) (
  21:   input  logic                   clk_i,       // Clock
  22:   input  logic                   rst_ni,
  23:   input  logic                   dmactive_i,  // synchronous reset active low
  24: 
  25:   output logic                   master_req_o,
  26:   output logic [BusWidth-1:0]    master_add_o,
  27:   output logic                   master_we_o,
  28:   output logic [BusWidth-1:0]    master_wdata_o,
  29:   output logic [BusWidth/8-1:0]  master_be_o,
  30:   input  logic                   master_gnt_i,
  31:   input  logic                   master_r_valid_i,
  32:   input  logic [BusWidth-1:0]    master_r_rdata_i,
  33: 
  34:   input  logic [BusWidth-1:0]    sbaddress_i,
  35:   input  logic                   sbaddress_write_valid_i,
  36:   // control signals in
  37:   input  logic                   sbreadonaddr_i,
  38:   output logic [BusWidth-1:0]    sbaddress_o,
  39:   input  logic                   sbautoincrement_i,
  40:   input  logic [2:0]             sbaccess_i,
  41:   // data in
  42:   input  logic                   sbreadondata_i,
  43:   input  logic [BusWidth-1:0]    sbdata_i,
  44:   input  logic                   sbdata_read_valid_i,
  45:   input  logic                   sbdata_write_valid_i,
  46:   // read data out
  47:   output logic [BusWidth-1:0]    sbdata_o,
  48:   output logic                   sbdata_valid_o,
  49:   // control signals
  50:   output logic                   sbbusy_o,
  51:   output logic                   sberror_valid_o, // bus error occurred
  52:   output logic [2:0]             sberror_o // bus error occurred
  53: );
  54: 
  55:   typedef enum logic [2:0] { Idle, Read, Write, WaitRead, WaitWrite } state_e;
  56:   state_e state_d, state_q;
  57: 
  58:   logic [BusWidth-1:0]           address;
  59:   logic                          req;
  60:   logic                          gnt;
  61:   logic                          we;
  62:   logic [BusWidth/8-1:0]         be;
  63:   logic [$clog2(BusWidth/8)-1:0] be_idx;
  64: 
  65:   assign sbbusy_o = logic'(state_q != Idle);
  66: 
  67:   always_comb begin : p_fsm
  68:     req     = 1'b0;
  69:     address = sbaddress_i;
  70:     we      = 1'b0;
  71:     be      = '0;
  72:     be_idx  = sbaddress_i[$clog2(BusWidth/8)-1:0];
  73: 
  74:     sberror_o       = '0;
  75:     sberror_valid_o = 1'b0;
  76:     sbaddress_o     = sbaddress_i;
  77: 
  78:     state_d = state_q;
  79: 
  80:     unique case (state_q)
  81:       Idle: begin
  82:         // debugger requested a read
  83:         if (sbaddress_write_valid_i && sbreadonaddr_i)  state_d = Read;
  84:         // debugger requested a write
  85:         if (sbdata_write_valid_i) state_d = Write;
  86:         // perform another read
  87:         if (sbdata_read_valid_i && sbreadondata_i) state_d = Read;
  88:       end
  89: 
  90:       Read: begin
  91:         req = 1'b1;
  92:         if (gnt) state_d = WaitRead;
  93:       end
  94: 
  95:       Write: begin
  96:         req = 1'b1;
  97:         we  = 1'b1;
  98:         // generate byte enable mask
  99:         unique case (sbaccess_i)
 100:           3'b000: begin
 101:             be[be_idx] = '1;
 102:           end
 103:           3'b001: begin
 104:             be[int'({be_idx[$high(be_idx):1], 1'b0}) +: 2] = '1;
 105:           end
 106:           3'b010: begin
 107:             if (BusWidth == 32'd64) be[int'({be_idx[$high(be_idx)], 2'b0}) +: 4] = '1;
 108:             else                    be = '1;
 109:           end
 110:           3'b011: be = '1;
 111:           default: ;
 112:         endcase
 113:         if (gnt) state_d = WaitWrite;
 114:       end
 115: 
 116:       WaitRead: begin
 117:         if (sbdata_valid_o) begin
 118:           state_d = Idle;
 119:           // auto-increment address
 120:           if (sbautoincrement_i) sbaddress_o = sbaddress_i + (32'b1 << sbaccess_i);
 121:         end
 122:       end
 123: 
 124:       WaitWrite: begin
 125:         if (sbdata_valid_o) begin
 126:           state_d = Idle;
 127:           // auto-increment address
 128:           if (sbautoincrement_i) sbaddress_o = sbaddress_i + (32'b1 << sbaccess_i);
 129:         end
 130:       end
 131: 
 132:       default: state_d = Idle; // catch parasitic state
 133:     endcase
 134: 
 135:     // handle error case
 136:     if (sbaccess_i > 3 && state_q != Idle) begin
 137:       req             = 1'b0;
 138:       state_d         = Idle;
 139:       sberror_valid_o = 1'b1;
 140:       sberror_o       = 3'd3;
 141:     end
 142:     // further error handling should go here ...
 143:   end
 144: 
 145:   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
 146:     if (!rst_ni) begin
 147:       state_q <= Idle;
 148:     end else begin
 149:       state_q <= state_d;
 150:     end
 151:   end
 152: 
 153:   assign master_req_o    = req;
 154:   assign master_add_o    = address[BusWidth-1:0];
 155:   assign master_we_o     = we;
 156:   assign master_wdata_o  = sbdata_i[BusWidth-1:0];
 157:   assign master_be_o     = be[BusWidth/8-1:0];
 158:   assign gnt             = master_gnt_i;
 159:   assign sbdata_valid_o  = master_r_valid_i;
 160:   assign sbdata_o        = master_r_rdata_i[BusWidth-1:0];
 161: 
 162: 
 163:   //pragma translate_off
 164:   `ifndef VERILATOR
 165:     // maybe bump severity to $error if not handled at runtime
 166:     dm_sba_access_size: assert property(@(posedge clk_i) disable iff (dmactive_i !== 1'b0)
 167:         (state_d != Idle) |-> (sbaccess_i < 4))
 168:             else $warning ("accesses > 8 byte not supported at the moment");
 169:   `endif
 170:   //pragma translate_on
 171: 
 172: endmodule : dm_sba
 173: